Merge branch 'master' into feature/EKSCatalog
Signed-off-by: Jonah Back <jonah@jonahback.com>
This commit is contained in:
+1
-2
@@ -223,8 +223,7 @@ For more information, see our
|
||||
|
||||
No, this is not a service offering. We build the piece of software, and someone
|
||||
in your infrastructure team is responsible for
|
||||
[deploying](https://backstage.io/docs/getting-started/deployment-k8s) and
|
||||
maintaining it.
|
||||
[deploying](https://backstage.io/docs/deployment) and maintaining it.
|
||||
|
||||
### How secure is Backstage?
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ In order to use the Bitbucket provider for sign-in, you must configure it with a
|
||||
`signIn.resolver`. See the
|
||||
[Sign-In Resolver documentation](../identity-resolver.md) for more details on
|
||||
how this is done. Note that for the Bitbucket provider, you'll want to use
|
||||
`bitbucket` as the provider ID, and `createBitbucketProvider` for the provider
|
||||
`bitbucket` as the provider ID, and `providers.bitbucket.create` for the provider
|
||||
factory.
|
||||
|
||||
The `@backstage/plugin-auth-backend` plugin also comes with two built-in
|
||||
@@ -74,16 +74,14 @@ same way, but uses the Bitbucket user ID instead, and matches on the
|
||||
The following is an example of how to use one of the built-in resolvers:
|
||||
|
||||
```ts
|
||||
import {
|
||||
createBitbucketProvider,
|
||||
bitbucketUsernameSignInResolver,
|
||||
} from '@backstage/plugin-auth-backend';
|
||||
import { providers } from '@backstage/plugin-auth-backend';
|
||||
|
||||
// ...
|
||||
providerFactories: {
|
||||
bitbucket: createBitbucketProvider({
|
||||
bitbucket: providers.bitbucket.create({
|
||||
signIn: {
|
||||
resolver: bitbucketUsernameSignInResolver,
|
||||
resolver:
|
||||
providers.bitbucket.resolvers.usernameMatchingUserEntityAnnotation(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -110,6 +110,7 @@ Now let's look at the example, with the rest of the commentary being made with i
|
||||
the code comments:
|
||||
|
||||
```ts
|
||||
// File: packages/backend/src/plugins/auth.ts
|
||||
import {
|
||||
createRouter,
|
||||
providers,
|
||||
@@ -170,11 +171,21 @@ property of each of the auth provider integrations. For example, the Google prov
|
||||
a built in resolver that works just like the one we defined above:
|
||||
|
||||
```ts
|
||||
providers.google.create({
|
||||
signIn: {
|
||||
resolver: providers.google.resolvers.emailLocalPartMatchingUserEntityName(),
|
||||
},
|
||||
});
|
||||
// File: packages/backend/src/plugins/auth.ts
|
||||
export default async function createPlugin(
|
||||
// ...
|
||||
return await createRouter({
|
||||
// ...
|
||||
providerFactories: {
|
||||
// ...
|
||||
google: providers.google.create({
|
||||
signIn: {
|
||||
resolver: providers.google.resolvers.emailLocalPartMatchingUserEntityName(),
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
)
|
||||
```
|
||||
|
||||
There are also other options, like the this one that looks up a user
|
||||
@@ -195,40 +206,49 @@ that happens during sign-in you can replace `ctx.signInWithCatalogUser` with a s
|
||||
of lower-level calls:
|
||||
|
||||
```ts
|
||||
// File: packages/backend/src/plugins/auth.ts
|
||||
import { getDefaultOwnershipRefs } from '@backstage/plugin-auth-backend';
|
||||
|
||||
// This example only shows the resolver function itself.
|
||||
async ({ profile: { email } }, ctx) => {
|
||||
if (!email) {
|
||||
throw new Error('User profile contained no email');
|
||||
}
|
||||
export default async function createPlugin(
|
||||
// ...
|
||||
return await createRouter({
|
||||
// ...
|
||||
providerFactories: {
|
||||
// ...
|
||||
google: async ({ profile: { email } }, ctx) => {
|
||||
if (!email) {
|
||||
throw new Error('User profile contained no email');
|
||||
}
|
||||
|
||||
// This step calls the catalog to look up a user entity. You could for example
|
||||
// replace it with a call to a different external system.
|
||||
const { entity } = await ctx.findCatalogUser({
|
||||
annotations: {
|
||||
'acme.org/email': email,
|
||||
},
|
||||
});
|
||||
// This step calls the catalog to look up a user entity. You could for example
|
||||
// replace it with a call to a different external system.
|
||||
const { entity } = await ctx.findCatalogUser({
|
||||
annotations: {
|
||||
'acme.org/email': email,
|
||||
},
|
||||
});
|
||||
|
||||
// In this step we extract the ownership references from the user entity using
|
||||
// the standard logic. It uses a reference to the entity itself, as well as the
|
||||
// target of each `memberOf` relation where the target is of the kind `Group`.
|
||||
//
|
||||
// If you replace the catalog lookup with something does not return
|
||||
// an entity you will need to replace this step as well.
|
||||
//
|
||||
// You might also replace it if you for example want to filter out certain groups.
|
||||
const ownershipRefs = getDefaultOwnershipRefs(entity);
|
||||
// In this step we extract the ownership references from the user entity using
|
||||
// the standard logic. It uses a reference to the entity itself, as well as the
|
||||
// target of each `memberOf` relation where the target is of the kind `Group`.
|
||||
//
|
||||
// If you replace the catalog lookup with something that does not return
|
||||
// an entity you will need to replace this step as well.
|
||||
//
|
||||
// You might also replace it if you for example want to filter out certain groups.
|
||||
const ownershipRefs = getDefaultOwnershipRefs(entity);
|
||||
|
||||
// The last step is to issue the token, where we might provide more options in the future.
|
||||
return ctx.issueToken({
|
||||
claims: {
|
||||
sub: stringifyEntityRef(entity),
|
||||
ent: ownershipRefs,
|
||||
},
|
||||
});
|
||||
};
|
||||
// The last step is to issue the token, where we might provide more options in the future.
|
||||
return ctx.issueToken({
|
||||
claims: {
|
||||
sub: stringifyEntityRef(entity),
|
||||
ent: ownershipRefs,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
})
|
||||
)
|
||||
```
|
||||
|
||||
## Sign-In without Users in the Catalog
|
||||
@@ -252,38 +272,47 @@ check like in the example below, or you might for example look up the GitHub org
|
||||
that the user belongs to using the user access token in the provided result object.
|
||||
|
||||
```ts
|
||||
// File: packages/backend/src/plugins/auth.ts
|
||||
import { DEFAULT_NAMESPACE, stringifyEntityRef, } from '@backstage/catalog-model';
|
||||
|
||||
// This example only shows the resolver function itself.
|
||||
async ({ profile }, ctx) => {
|
||||
if (!profile.email) {
|
||||
throw new Error(
|
||||
'Login failed, user profile does not contain an email',
|
||||
);
|
||||
}
|
||||
// Split the email into the local part and the domain.
|
||||
const [localPart, domain] = profile.email.split('@');
|
||||
export default async function createPlugin(
|
||||
// ...
|
||||
return await createRouter({
|
||||
// ...
|
||||
providerFactories: {
|
||||
// ...
|
||||
google: async ({ profile }, ctx) => {
|
||||
if (!profile.email) {
|
||||
throw new Error(
|
||||
'Login failed, user profile does not contain an email',
|
||||
);
|
||||
}
|
||||
// Split the email into the local part and the domain.
|
||||
const [localPart, domain] = profile.email.split('@');
|
||||
|
||||
// Next we verify the email domain. It is recommended to include this
|
||||
// kind of check if you don't look up the user in an external service.
|
||||
if (domain !== 'acme.org') {
|
||||
throw new Error('Login failed, user email domain check failed');
|
||||
}
|
||||
// Next we verify the email domain. It is recommended to include this
|
||||
// kind of check if you don't look up the user in an external service.
|
||||
if (domain !== 'acme.org') {
|
||||
throw new Error('Login failed, user email domain check failed');
|
||||
}
|
||||
|
||||
// By using `stringifyEntityRef` we ensure that the reference is formatted correctly
|
||||
const userEntityRef = stringifyEntityRef({
|
||||
kind: 'User',
|
||||
name: localPart,
|
||||
namespace: DEFAULT_NAMESPACE,
|
||||
});
|
||||
// By using `stringifyEntityRef` we ensure that the reference is formatted correctly
|
||||
const userEntityRef = stringifyEntityRef({
|
||||
kind: 'User',
|
||||
name: localPart,
|
||||
namespace: DEFAULT_NAMESPACE,
|
||||
});
|
||||
|
||||
return ctx.issueToken({
|
||||
claims: {
|
||||
sub: userEntityRef,
|
||||
ent: [userEntityRef],
|
||||
},
|
||||
});
|
||||
},
|
||||
return ctx.issueToken({
|
||||
claims: {
|
||||
sub: userEntityRef,
|
||||
ent: [userEntityRef],
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
```
|
||||
|
||||
## AuthHandler
|
||||
@@ -304,7 +333,7 @@ export default async function createPlugin(
|
||||
return await createRouter({
|
||||
...
|
||||
providerFactories: {
|
||||
google: createGoogleProvider({
|
||||
google: providers.google.create({
|
||||
authHandler: async ({
|
||||
fullProfile // Type: passport.Profile,
|
||||
idToken // Type: (Optional) string,
|
||||
|
||||
@@ -74,6 +74,12 @@ techdocs:
|
||||
|
||||
type: 'local'
|
||||
|
||||
# Optional when techdocs.publisher.type is set to 'local'.
|
||||
|
||||
local:
|
||||
# (Optional). Set this to specify where the generated documentation is stored.
|
||||
publishDirectory: '/path/to/local/directory'
|
||||
|
||||
# Required when techdocs.publisher.type is set to 'googleGcs'. Skip otherwise.
|
||||
|
||||
googleGcs:
|
||||
|
||||
@@ -155,6 +155,8 @@ auth:
|
||||
clientSecret: YOUR CLIENT SECRET
|
||||
```
|
||||
|
||||
### Add sign-in option to the frontend
|
||||
|
||||
Backstage will re-read the configuration. If there's no errors, that's great! We
|
||||
can continue with the last part of the configuration. The next step is needed to
|
||||
change the sign-in page, this you actually need to add in the source code.
|
||||
@@ -185,10 +187,11 @@ components: {
|
||||
},
|
||||
```
|
||||
|
||||
> Since [v1.1.0](https://github.com/backstage/backstage/releases/tag/v1.1.0-next.3), you must provide an [explicit sign-in resolver](../auth/identity-resolver.md).
|
||||
> Note: The default Backstage app comes with a guest Sign In Resolver. This resolver makes all users share a single "guest" identity and is only intended as a minimum requirement to quickly get up and running. You can read more about how [Sign In Resolvers](../auth/identity-resolver.md#sign-in-resolvers) play a role in creating a [Backstage User Identity](../auth/identity-resolver.md#backstage-user-identity) for logged in users.
|
||||
|
||||
That should be it. You can stop your Backstage App. When you start it again and
|
||||
go to your Backstage portal in your browser, you should have your login prompt!
|
||||
Restart Backstage from the terminal, by stopping it with `Control-C`, and starting it with `yarn dev` . You should be welcomed by a login prompt!
|
||||
|
||||
> Note: Sometimes the frontend starts before the backend resulting in errors on the sign in page. Wait for the backend to start and then reload Backstage to proceed.
|
||||
|
||||
To learn more about Authentication in Backstage, here are some docs you
|
||||
could read:
|
||||
|
||||
@@ -157,7 +157,7 @@ export const HomePage = () => {
|
||||
return (
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12} md={4}>
|
||||
<HomePageCompanyLogo className={container} />
|
||||
<HomePageCompanyLogo />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
@@ -28,7 +28,7 @@ the code.
|
||||
sub-folder which is used for a markdown spellchecker.
|
||||
|
||||
- [`.yarn/`](https://github.com/backstage/backstage/tree/master/.yarn) -
|
||||
Backstage ships with it's own `yarn` implementation. This allows us to have
|
||||
Backstage ships with its own `yarn` implementation. This allows us to have
|
||||
better control over our `yarn.lock` file and hopefully avoid problems due to
|
||||
yarn versioning differences.
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ catalog:
|
||||
anotherProviderId: # another identifier
|
||||
organization: myorg
|
||||
project: myproject
|
||||
repository: '*' # this will match all repos starting with service-*
|
||||
repository: '*' # this will match all repos
|
||||
path: /src/*/catalog-info.yaml # this will search for files deep inside the /src folder
|
||||
yetAotherProviderId: # guess, what? Another one :)
|
||||
host: selfhostedazure.yourcompany.com
|
||||
|
||||
@@ -22,7 +22,7 @@ catalog:
|
||||
yourProviderId:
|
||||
host: gitlab-host # Identifies one of the hosts set up in the integrations
|
||||
branch: main # Optional. Uses `master` as default
|
||||
group: example-group # Group and subgroup (if needed) to look for repositories
|
||||
group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole project will be scanned
|
||||
entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml`
|
||||
```
|
||||
|
||||
|
||||
@@ -135,3 +135,21 @@ package export.
|
||||
accessed via `<package-name>/beta` or `<package-name>/alpha` imports.
|
||||
- `@alpha` - here be dragons. Not visible in the main package entry point, alpha
|
||||
exports must be accessed via `<package-name>/alpha` imports.
|
||||
|
||||
## Node.js Releases
|
||||
|
||||
The Backstage project uses [Node.js](https://nodejs.org/) for both its development
|
||||
tooling and backend runtime. In order for expectations to be clear we use the
|
||||
following schedule for determining the [Node.js releases](https://nodejs.org/en/about/releases/) that we support:
|
||||
|
||||
- At any given point in time we support exactly two adjacent even-numbered
|
||||
releases of Node.js, for example v12 and v14.
|
||||
- Three months before a Node.js release becomes _Active LTS_ we switch support
|
||||
to that release and the previous one. This is halfway through the _Current LTS_
|
||||
cycle for that release and occurs at the end of July every year.
|
||||
|
||||
When we say _Supporting_ a Node.js release, that means the following:
|
||||
|
||||
- The CI pipeline in the main Backstage repo tests towards the supported releases, and we encourage any other Backstage related projects to do the same.
|
||||
- New Backstage projects created with `@backstage/create-app` will have their `engines.node` version set accordingly.
|
||||
- Dropping compatibility with unsupported releases is not considered a breaking change. This includes using new syntax or APIs, as well as bumping dependencies that drop support for these versions.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user