Merge branch 'backstage:master' into feat/scaffolder-add-edit-action
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Bumped create-app version.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-react': minor
|
||||
'@backstage/plugin-catalog-import': minor
|
||||
'@backstage/plugin-kubernetes': patch
|
||||
'@backstage/plugin-search': patch
|
||||
---
|
||||
|
||||
Migrate from identityApi to fetchApi in frontend plugins.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-notifications': patch
|
||||
---
|
||||
|
||||
Fixes performance issue with Notifications title counter.
|
||||
@@ -190,33 +190,63 @@
|
||||
"calm-plums-wink",
|
||||
"cold-seas-end",
|
||||
"create-app-1716302437",
|
||||
"create-app-1716903719",
|
||||
"cyan-jobs-visit",
|
||||
"cyan-paws-beg",
|
||||
"cyan-snails-peel",
|
||||
"eighty-kings-dress",
|
||||
"eighty-yaks-switch",
|
||||
"empty-spoons-tell",
|
||||
"empty-tables-ring",
|
||||
"famous-monkeys-count",
|
||||
"forty-adults-roll",
|
||||
"four-adults-mix",
|
||||
"friendly-keys-fold",
|
||||
"gentle-baboons-peel",
|
||||
"gold-teachers-wink",
|
||||
"great-cougars-guess",
|
||||
"itchy-spoons-cry",
|
||||
"large-months-decide",
|
||||
"late-ants-impress",
|
||||
"late-students-live",
|
||||
"little-cooks-approve",
|
||||
"loud-pumpkins-bow",
|
||||
"lovely-hats-pay",
|
||||
"lucky-taxis-rule",
|
||||
"many-moles-sing",
|
||||
"mean-laws-lay",
|
||||
"neat-rivers-share",
|
||||
"new-numbers-hug",
|
||||
"nice-pants-shave",
|
||||
"nine-hairs-kick",
|
||||
"nine-ties-type",
|
||||
"old-trees-check",
|
||||
"olive-mangos-tickle",
|
||||
"perfect-bikes-invite",
|
||||
"polite-otters-talk",
|
||||
"rude-kings-press",
|
||||
"seven-geese-raise",
|
||||
"shaggy-jokes-promise",
|
||||
"six-llamas-give",
|
||||
"slimy-fans-raise",
|
||||
"smooth-gifts-nail",
|
||||
"soft-flies-live",
|
||||
"sour-colts-juggle",
|
||||
"spicy-brooms-hang",
|
||||
"spicy-camels-happen",
|
||||
"spotty-plants-switch",
|
||||
"strong-moose-work",
|
||||
"stupid-tigers-bake",
|
||||
"tall-lies-fetch",
|
||||
"tall-pumas-teach",
|
||||
"tender-seas-listen",
|
||||
"thirty-plums-shout",
|
||||
"tiny-pandas-return",
|
||||
"warm-bees-hope",
|
||||
"weak-gifts-occur",
|
||||
"wet-crabs-guess",
|
||||
"wild-doors-cheat",
|
||||
"wild-ears-walk",
|
||||
"wise-vans-sin",
|
||||
"wise-wasps-look",
|
||||
"young-camels-return"
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-react': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Fixing bug in `formData` type as it should be `optional` as it's possibly undefined
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-ldap': minor
|
||||
---
|
||||
|
||||
Migrate LDAP catalog module to the new backend system.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-backend': minor
|
||||
'@backstage/plugin-kubernetes-common': minor
|
||||
'@backstage/plugin-kubernetes-react': minor
|
||||
---
|
||||
|
||||
Update kubernetes plugins to use autoscaling/v2
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Added a regex test to check commit hash. If url is from git commit branch ignore the edit url.
|
||||
@@ -41,18 +41,16 @@ jobs:
|
||||
run: |
|
||||
yarn backstage-repo-tools repo schema openapi diff --since origin/${{ github.base_ref }} > comment.md
|
||||
|
||||
- name: Upload Rendered Comment as Artifact
|
||||
- name: clone artifacts to current directory
|
||||
run: |
|
||||
cat ${{ github.event_path }} > event.json
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
|
||||
with:
|
||||
name: preview-spec
|
||||
path: comment.md
|
||||
retention-days: 2
|
||||
overwrite: true
|
||||
|
||||
- name: Upload PR Event as Artifact
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
with:
|
||||
name: preview-spec
|
||||
path: ${{ github.event_path }}
|
||||
path: |
|
||||
comment.md
|
||||
event.json
|
||||
retention-days: 2
|
||||
overwrite: true
|
||||
|
||||
@@ -97,18 +97,19 @@ jobs:
|
||||
kustomize edit set image backstage=${{ needs.build-backstage.outputs.tags }}
|
||||
kustomize build . > manifests.rendered.yml
|
||||
cat manifests.rendered.yml
|
||||
- name: Upload Rendered Manifests File as Artifact
|
||||
|
||||
- name: clone artifacts into current directory
|
||||
run: |
|
||||
cat ${{ github.event_path }} > event.json
|
||||
cp ./.github/uffizzi/k8s/manifests/manifests.rendered.yml manifests.rendered.yml
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
|
||||
with:
|
||||
name: preview-spec
|
||||
path: ./.github/uffizzi/k8s/manifests/manifests.rendered.yml
|
||||
retention-days: 2
|
||||
overwrite: true
|
||||
- name: Upload PR Event as Artifact
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
with:
|
||||
name: preview-spec
|
||||
path: ${{ github.event_path }}
|
||||
path: |
|
||||
manifests.rendered.yml
|
||||
event.json
|
||||
retention-days: 2
|
||||
overwrite: true
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ There are only two possible scopes for services, `'plugin'` and `'root'`.
|
||||
|
||||
## Root Scoped Services
|
||||
|
||||
If a service is defined as a root scoped service, the implementation created by the factory will be shared across all plugins and services. One other differentiating factory for root scoped services is that they are always initialized, regardless of whether any plugins depend on them or not. This makes them suitable for implementing backend-wide concerns that are not specific to any individual plugin.
|
||||
If a service is defined as a root scoped service, the implementation created by the factory will be shared across all plugins and services. One other differentiating factor for root scoped services is that they are always initialized, regardless of whether any plugins depend on them or not. This makes them suitable for implementing backend-wide concerns that are not specific to any individual plugin.
|
||||
|
||||
There is a limitation in the usage of root scoped services, which is that their implementation can only depend on other root scoped services. Plugin scoped services on the other hand can depend on both root and plugin scoped services. Because of this limitation, one of the main reasons to define a root scoped services is to make it possible for other root scoped services to depend on it.
|
||||
|
||||
@@ -157,7 +157,7 @@ export const fooServiceFactory = createServiceFactory({
|
||||
});
|
||||
```
|
||||
|
||||
Whatever value is returned by the `createRootContext` function will shared and passed as the second argument to each invocation of the `factory` function. That way you can create a shared context that is used in the creation of each plugin instance. Unlike the `factory` function, the `createRootContext` function will only receive root scoped services as its dependencies, but just like the `factory` function, it can also be `async`.
|
||||
Whatever value is returned by the `createRootContext` function will be shared and passed as the second argument to each invocation of the `factory` function. That way you can create a shared context that is used in the creation of each plugin instance. Unlike the `factory` function, the `createRootContext` function will only receive root scoped services as its dependencies, but just like the `factory` function, it can also be `async`.
|
||||
|
||||
## Default Service Factories
|
||||
|
||||
|
||||
@@ -1369,7 +1369,7 @@ The vast majority of the backend plugins that currently live in the Backstage Re
|
||||
| @backstage/plugin-catalog-backend-module-github-org | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-github-org/README.md) |
|
||||
| @backstage/plugin-catalog-backend-module-gitlab | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-gitlab/README.md) |
|
||||
| @backstage/plugin-catalog-backend-module-incremental-ingestion | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-incremental-ingestion/README.md) |
|
||||
| @backstage/plugin-catalog-backend-module-ldap | backend-plugin-module | | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-ldap/README.md) |
|
||||
| @backstage/plugin-catalog-backend-module-ldap | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-ldap/README.md) |
|
||||
| @backstage/plugin-catalog-backend-module-msgraph | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/README.md) |
|
||||
| @backstage/plugin-catalog-backend-module-openapi | backend-plugin-module | true | | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-openapi/README.md) |
|
||||
| @backstage/plugin-catalog-backend-module-puppetdb | backend-plugin-module | true | true | [README](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-puppetdb/README.md) |
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
---
|
||||
id: org--old
|
||||
title: LDAP Organizational Data
|
||||
sidebar_label: Org Data
|
||||
# prettier-ignore
|
||||
description: Setting up ingestion of organizational data from LDAP
|
||||
---
|
||||
|
||||
The Backstage catalog can be set up to ingest organizational data - users and
|
||||
groups - directly from an LDAP compatible service. The result is a hierarchy of
|
||||
[`User`](../../features/software-catalog/descriptor-format.md#kind-user) and
|
||||
[`Group`](../../features/software-catalog/descriptor-format.md#kind-group) kind
|
||||
entities that mirror your org setup.
|
||||
|
||||
## Supported vendors
|
||||
|
||||
Backstage in general supports OpenLDAP compatible vendors, as well as Active Directory and FreeIPA. If you are using a vendor that does not seem to be supported, please [file an issue](https://github.com/backstage/backstage/issues/new?assignees=&labels=enhancement&template=feature_template.md).
|
||||
|
||||
## Installation
|
||||
|
||||
This guide will use the Entity Provider method. If you for some reason prefer
|
||||
the Processor method (not recommended), it is described separately below.
|
||||
|
||||
The provider is not installed by default, therefore you have to add a dependency
|
||||
to `@backstage/plugin-catalog-backend-module-ldap` to your backend package.
|
||||
|
||||
```bash
|
||||
# From your Backstage root directory
|
||||
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-ldap
|
||||
```
|
||||
|
||||
:::note Note
|
||||
|
||||
When configuring to use a Provider instead of a Processor you do not
|
||||
need to add a _location_ pointing to your LDAP server
|
||||
|
||||
:::
|
||||
|
||||
Update the catalog plugin initialization in your backend to add the provider and
|
||||
schedule it:
|
||||
|
||||
```ts title="packages/backend/src/plugins/catalog.ts"
|
||||
/* highlight-add-next-line */
|
||||
import { LdapOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-ldap';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
|
||||
/* highlight-add-start */
|
||||
// The target parameter below needs to match the ldap.providers.target
|
||||
// value specified in your app-config.
|
||||
builder.addEntityProvider(
|
||||
LdapOrgEntityProvider.fromConfig(env.config, {
|
||||
id: 'our-ldap-master',
|
||||
target: 'ldaps://ds.example.net',
|
||||
logger: env.logger,
|
||||
schedule: env.scheduler.createScheduledTaskRunner({
|
||||
frequency: { minutes: 60 },
|
||||
timeout: { minutes: 15 },
|
||||
}),
|
||||
}),
|
||||
);
|
||||
/* highlight-add-end */
|
||||
|
||||
// ..
|
||||
}
|
||||
```
|
||||
|
||||
After this, you also have to add some configuration in your app-config that
|
||||
describes what you want to import for that target.
|
||||
|
||||
## Configuration
|
||||
|
||||
The following configuration is a small example of how a setup could look for
|
||||
importing groups and users from a corporate LDAP server.
|
||||
|
||||
```yaml
|
||||
ldap:
|
||||
providers:
|
||||
- target: ldaps://ds.example.net
|
||||
bind:
|
||||
dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net
|
||||
secret: ${LDAP_SECRET}
|
||||
users:
|
||||
dn: ou=people,ou=example,dc=example,dc=net
|
||||
options:
|
||||
filter: (uid=*)
|
||||
map:
|
||||
description: l
|
||||
set:
|
||||
metadata.customField: 'hello'
|
||||
groups:
|
||||
dn: ou=access,ou=groups,ou=example,dc=example,dc=net
|
||||
options:
|
||||
filter: (&(objectClass=some-group-class)(!(groupType=email)))
|
||||
map:
|
||||
description: l
|
||||
set:
|
||||
metadata.customField: 'hello'
|
||||
```
|
||||
|
||||
There may be many providers, each targeting a specific `target` which is
|
||||
supposed to match the `target` of a dedicated provider instance - i.e., you will
|
||||
add one entity provider class instance per target to ingest from.
|
||||
|
||||
These config blocks have a lot of options in them, so we will describe each
|
||||
"root" key within the block separately.
|
||||
|
||||
### target
|
||||
|
||||
This is the URL of the targeted server, typically on the form
|
||||
`ldaps://ds.example.net` for SSL enabled servers or `ldap://ds.example.net`
|
||||
without SSL.
|
||||
|
||||
#### target.tls.keys
|
||||
|
||||
`keys` in TLS options specifies location of a file, that contains private keys
|
||||
to establish connection with your LDAP server, in PEM format. See an example
|
||||
for Google Secure LDAP Service below.
|
||||
|
||||
#### target.tls.certs
|
||||
|
||||
`certs` in TLS options specifies location of a file, that contains certificate
|
||||
chains to establish connection with your LDAP server, in PEM format. See an
|
||||
example for Google Secure LDAP Service below.
|
||||
|
||||
### bind
|
||||
|
||||
The bind block specifies how the plugin should bind (essentially, to
|
||||
authenticate) towards the server. It has the following fields.
|
||||
|
||||
```yaml
|
||||
dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net
|
||||
secret: ${LDAP_SECRET}
|
||||
```
|
||||
|
||||
The `dn` is the full LDAP Distinguished Name for the user that the plugin
|
||||
authenticates itself as. At this point, only regular user based authentication
|
||||
is supported.
|
||||
|
||||
The `secret` is the password of the same user. In this example, it is given in
|
||||
the form of an environment variable `LDAP_SECRET`, that has to be set when the
|
||||
backend starts.
|
||||
|
||||
### users
|
||||
|
||||
The `users` block defines the settings that govern the reading and
|
||||
interpretation of users. Its fields are explained in separate sections below.
|
||||
|
||||
#### users.dn
|
||||
|
||||
The DN under which users are stored, e.g.
|
||||
`ou=people,ou=example,dc=example,dc=net`.
|
||||
|
||||
#### users.options
|
||||
|
||||
The search options to use when sending the query to the server, when reading all
|
||||
users. All the options are shown below, with their default values, but they are
|
||||
all optional.
|
||||
|
||||
```yaml
|
||||
options:
|
||||
# One of 'base', 'one', or 'sub'.
|
||||
scope: one
|
||||
# The filter is the one that you commonly will want to specify explicitly. It
|
||||
# is a string on the standard LDAP query format. Use it to select out the set
|
||||
# of users that are of actual interest to ingest. For example, you may want
|
||||
# to filter out disabled users.
|
||||
filter: (uid=*)
|
||||
# The attribute selectors for each item, as passed to the LDAP server.
|
||||
attributes: ['*', '+']
|
||||
# This field is either 'false' to disable paging when reading from the
|
||||
# server, or an object on the form '{ pageSize: 100, pagePause: true }' that
|
||||
# specifies the details of how the paging shall work.
|
||||
paged: false
|
||||
```
|
||||
|
||||
#### users.set
|
||||
|
||||
This optional piece lets you specify a number of JSON paths (on a.b.c form) and
|
||||
hard coded values to set on those paths. This can be useful for example if you
|
||||
want to hard code a namespace or similar on the generated entities.
|
||||
|
||||
```yaml
|
||||
set:
|
||||
# Just an example; the key and value can be anything
|
||||
metadata.namespace: 'ldap'
|
||||
```
|
||||
|
||||
#### users.map
|
||||
|
||||
Mappings from well known entity fields, to LDAP attribute names. This is where
|
||||
you are able to define how to interpret the attributes of each LDAP result item,
|
||||
and to move them into the corresponding entity fields. All the options are shown
|
||||
below, with their default values, but they are all optional.
|
||||
|
||||
If you leave out an optional mapping, it will still be copied using that default
|
||||
value. For example, even if you do not put in the field `displayName` in your
|
||||
config, the provider will still copy the attribute `cn` into the entity field
|
||||
`spec.profile.displayName`.
|
||||
|
||||
```yaml
|
||||
map:
|
||||
# The name of the attribute that holds the relative
|
||||
# distinguished name of each entry.
|
||||
rdn: uid
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the metadata.name field of the entity.
|
||||
name: uid
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the metadata.description field of the entity.
|
||||
description: description
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the spec.profile.displayName field of the entity.
|
||||
displayName: cn
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the spec.profile.email field of the entity.
|
||||
email: mail
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the spec.profile.picture field of the entity.
|
||||
picture: <nothing, left out>
|
||||
# The name of the attribute that shall be used for the values of
|
||||
# the spec.memberOf field of the entity.
|
||||
memberOf: memberOf
|
||||
```
|
||||
|
||||
### groups
|
||||
|
||||
The `groups` block defines the settings that govern the reading and
|
||||
interpretation of groups. Its fields are explained in separate sections below.
|
||||
|
||||
#### groups.dn
|
||||
|
||||
The DN under which groups are stored, e.g.
|
||||
`ou=people,ou=example,dc=example,dc=net`.
|
||||
|
||||
#### groups.options
|
||||
|
||||
The search options to use when sending the query to the server, when reading all
|
||||
groups. All the options are shown below, with their default values, but they are
|
||||
all optional.
|
||||
|
||||
```yaml
|
||||
options:
|
||||
# One of 'base', 'one', or 'sub'.
|
||||
scope: one
|
||||
# The filter is the one that you commonly will want to specify explicitly. It
|
||||
# is a string on the standard LDAP query format. Use it to select out the set
|
||||
# of groups that are of actual interest to ingest. For example, you may want
|
||||
# to filter out disabled groups.
|
||||
filter: (&(objectClass=some-group-class)(!(groupType=email)))
|
||||
# The attribute selectors for each item, as passed to the LDAP server.
|
||||
attributes: ['*', '+']
|
||||
# This field is either 'false' to disable paging when reading from the
|
||||
# server, or an object on the form '{ pageSize: 100, pagePause: true }' that
|
||||
# specifies the details of how the paging shall work.
|
||||
paged: false
|
||||
```
|
||||
|
||||
#### groups.set
|
||||
|
||||
This optional piece lets you specify a number of JSON paths (on a.b.c form) and
|
||||
hard coded values to set on those paths. This can be useful for example if you
|
||||
want to hard code a namespace or similar on the generated entities.
|
||||
|
||||
```yaml
|
||||
set:
|
||||
# Just an example; the key and value can be anything
|
||||
metadata.namespace: 'ldap'
|
||||
```
|
||||
|
||||
#### groups.map
|
||||
|
||||
Mappings from well known entity fields, to LDAP attribute names. This is where
|
||||
you are able to define how to interpret the attributes of each LDAP result item,
|
||||
and to move them into the corresponding entity fields. All of the options are
|
||||
shown below, with their default values, but they are all optional.
|
||||
|
||||
If you leave out an optional mapping, it will still be copied using that default
|
||||
value. For example, even if you do not put in the field `displayName` in your
|
||||
config, the provider will still copy the attribute `cn` into the entity field
|
||||
`spec.profile.displayName`. If the target field is optional, such as the display
|
||||
name, the importer will accept missing attributes and just leave the target
|
||||
field unset. If the target field is mandatory, such as the name of the entity,
|
||||
validation will fail if the source attribute is missing.
|
||||
|
||||
```yaml
|
||||
map:
|
||||
# The name of the attribute that holds the relative
|
||||
# distinguished name of each entry. This value is copied into a
|
||||
# well known annotation to be able to query by it later.
|
||||
rdn: cn
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the metadata.name field of the entity.
|
||||
name: cn
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the metadata.description field of the entity.
|
||||
description: description
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the spec.type field of the entity.
|
||||
type: groupType
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the spec.profile.displayName field of the entity.
|
||||
displayName: cn
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the spec.profile.email field of the entity.
|
||||
email: <nothing, left out>
|
||||
# The name of the attribute that shall be used for the value of
|
||||
# the spec.profile.picture field of the entity.
|
||||
picture: <nothing, left out>
|
||||
# The name of the attribute that shall be used for the values of
|
||||
# the spec.parent field of the entity.
|
||||
memberOf: memberOf
|
||||
# The name of the attribute that shall be used for the values of
|
||||
# the spec.children field of the entity.
|
||||
members: member
|
||||
```
|
||||
|
||||
## Customize the Provider
|
||||
|
||||
In case you want to customize the ingested entities, the provider allows to pass
|
||||
transformers for users and groups. Here we will show an example of overriding
|
||||
the group transformer.
|
||||
|
||||
1. Create a transformer:
|
||||
|
||||
```ts
|
||||
export async function myGroupTransformer(
|
||||
vendor: LdapVendor,
|
||||
config: GroupConfig,
|
||||
group: SearchEntry,
|
||||
): Promise<GroupEntity | undefined> {
|
||||
// Transformations may change namespace, change entity naming pattern, fill
|
||||
// profile with more or other details...
|
||||
|
||||
// Create the group entity on your own, or wrap the default transformer
|
||||
return await defaultGroupTransformer(vendor, config, group);
|
||||
}
|
||||
```
|
||||
|
||||
2. Configure the provider with the transformer:
|
||||
|
||||
```ts
|
||||
const ldapEntityProvider = LdapOrgEntityProvider.fromConfig(env.config, {
|
||||
id: 'our-ldap-master',
|
||||
target: 'ldaps://ds.example.net',
|
||||
logger: env.logger,
|
||||
groupTransformer: myGroupTransformer,
|
||||
});
|
||||
```
|
||||
|
||||
## Using a Processor instead of a Provider
|
||||
|
||||
An alternative to using the Provider for ingesting LDAP entries is to use a
|
||||
Processor. This is the old way that's based on registering locations with the
|
||||
proper type and target, triggering the processor to run.
|
||||
|
||||
The drawback of this method is that it will leave orphaned Group/User entities
|
||||
whenever they are deleted on your LDAP server, and you cannot control the
|
||||
frequency with which they are refreshed, separately from other processors.
|
||||
|
||||
### Processor Installation
|
||||
|
||||
The `LdapOrgReaderProcessor` is not registered by default, so you have to
|
||||
register it in the catalog plugin:
|
||||
|
||||
```typescript title="packages/backend/src/plugins/catalog.ts"
|
||||
builder.addProcessor(
|
||||
LdapOrgReaderProcessor.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
### Driving LDAP Org Processor Ingestion with Locations
|
||||
|
||||
Locations point out the specific org(s) you want to import. The `type` of these
|
||||
locations must be `ldap-org`, and the `target` must point to the exact URL
|
||||
(starting with `ldap://` or `ldaps://`) of the targeted LDAP server. You can
|
||||
have several such location entries if you want, but typically you will have just
|
||||
one.
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
- type: ldap-org
|
||||
target: ldaps://ds.example.net
|
||||
rules:
|
||||
- allow: [User, Group]
|
||||
```
|
||||
|
||||
### Example configurations
|
||||
|
||||
#### Google Secure LDAP Service
|
||||
|
||||
To sync Google Workspace/Cloud Identity organization data to users and groups in backstage,
|
||||
you must [configure Secure LDAP Service](https://support.google.com/a/answer/9048516) first.
|
||||
|
||||
Once Secure LDAP Service is configured, you can enable TLS options in LDAP configuration,
|
||||
as mentioned below. `keys` and `certs` specify the location of files that are generated
|
||||
while configuring Secure LDAP Service above.
|
||||
|
||||
```yaml
|
||||
ldap:
|
||||
providers:
|
||||
- target: ldaps://ldap.google.com:636
|
||||
tls:
|
||||
rejectUnauthorized: false
|
||||
keys: '/var/secrets/tls/gldap.key'
|
||||
certs: '/var/secrets/tls/gldap.crt'
|
||||
users:
|
||||
# users configuration comes here
|
||||
groups:
|
||||
# groups configuration comes here
|
||||
```
|
||||
+69
-154
@@ -18,9 +18,6 @@ Backstage in general supports OpenLDAP compatible vendors, as well as Active Dir
|
||||
|
||||
## Installation
|
||||
|
||||
This guide will use the Entity Provider method. If you for some reason prefer
|
||||
the Processor method (not recommended), it is described separately below.
|
||||
|
||||
The provider is not installed by default, therefore you have to add a dependency
|
||||
to `@backstage/plugin-catalog-backend-module-ldap` to your backend package.
|
||||
|
||||
@@ -29,47 +26,30 @@ to `@backstage/plugin-catalog-backend-module-ldap` to your backend package.
|
||||
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-ldap
|
||||
```
|
||||
|
||||
:::note Note
|
||||
Next add the basic configuration to `app-config.yaml`
|
||||
|
||||
When configuring to use a Provider instead of a Processor you do not
|
||||
need to add a _location_ pointing to your LDAP server
|
||||
|
||||
:::
|
||||
|
||||
Update the catalog plugin initialization in your backend to add the provider and
|
||||
schedule it:
|
||||
|
||||
```ts title="packages/backend/src/plugins/catalog.ts"
|
||||
/* highlight-add-next-line */
|
||||
import { LdapOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-ldap';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
|
||||
/* highlight-add-start */
|
||||
// The target parameter below needs to match the ldap.providers.target
|
||||
// value specified in your app-config.
|
||||
builder.addEntityProvider(
|
||||
LdapOrgEntityProvider.fromConfig(env.config, {
|
||||
id: 'our-ldap-master',
|
||||
target: 'ldaps://ds.example.net',
|
||||
logger: env.logger,
|
||||
schedule: env.scheduler.createScheduledTaskRunner({
|
||||
frequency: { minutes: 60 },
|
||||
timeout: { minutes: 15 },
|
||||
}),
|
||||
}),
|
||||
);
|
||||
/* highlight-add-end */
|
||||
|
||||
// ..
|
||||
}
|
||||
```yaml title="app-config.yaml"
|
||||
catalog:
|
||||
providers:
|
||||
ldapOrg:
|
||||
default:
|
||||
target: ldaps://ds.example.net
|
||||
bind:
|
||||
dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net
|
||||
secret: ${LDAP_SECRET}
|
||||
schedule:
|
||||
frequency: PT1H
|
||||
timeout: PT15M
|
||||
```
|
||||
|
||||
After this, you also have to add some configuration in your app-config that
|
||||
describes what you want to import for that target.
|
||||
Finally, updated your backend by adding the following line:
|
||||
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
backend.add(import('@backstage/plugin-catalog-backend/alpha'));
|
||||
/* highlight-add-start */
|
||||
backend.add(import('@backstage/plugin-catalog-backend-module-ldap'));
|
||||
/* highlight-add-end */
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -77,34 +57,32 @@ The following configuration is a small example of how a setup could look for
|
||||
importing groups and users from a corporate LDAP server.
|
||||
|
||||
```yaml
|
||||
ldap:
|
||||
catalog:
|
||||
providers:
|
||||
- target: ldaps://ds.example.net
|
||||
bind:
|
||||
dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net
|
||||
secret: ${LDAP_SECRET}
|
||||
users:
|
||||
dn: ou=people,ou=example,dc=example,dc=net
|
||||
options:
|
||||
filter: (uid=*)
|
||||
map:
|
||||
description: l
|
||||
set:
|
||||
metadata.customField: 'hello'
|
||||
groups:
|
||||
dn: ou=access,ou=groups,ou=example,dc=example,dc=net
|
||||
options:
|
||||
filter: (&(objectClass=some-group-class)(!(groupType=email)))
|
||||
map:
|
||||
description: l
|
||||
set:
|
||||
metadata.customField: 'hello'
|
||||
ldapOrg:
|
||||
default:
|
||||
target: ldaps://ds.example.net
|
||||
bind:
|
||||
dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net
|
||||
secret: ${LDAP_SECRET}
|
||||
users:
|
||||
dn: ou=people,ou=example,dc=example,dc=net
|
||||
options:
|
||||
filter: (uid=*)
|
||||
map:
|
||||
description: l
|
||||
set:
|
||||
metadata.customField: 'hello'
|
||||
groups:
|
||||
dn: ou=access,ou=groups,ou=example,dc=example,dc=net
|
||||
options:
|
||||
filter: (&(objectClass=some-group-class)(!(groupType=email)))
|
||||
map:
|
||||
description: l
|
||||
set:
|
||||
metadata.customField: 'hello'
|
||||
```
|
||||
|
||||
There may be many providers, each targeting a specific `target` which is
|
||||
supposed to match the `target` of a dedicated provider instance - i.e., you will
|
||||
add one entity provider class instance per target to ingest from.
|
||||
|
||||
These config blocks have a lot of options in them, so we will describe each
|
||||
"root" key within the block separately.
|
||||
|
||||
@@ -321,97 +299,34 @@ map:
|
||||
## Customize the Provider
|
||||
|
||||
In case you want to customize the ingested entities, the provider allows to pass
|
||||
transformers for users and groups. Here we will show an example of overriding
|
||||
the group transformer.
|
||||
transformers for users and groups.
|
||||
|
||||
1. Create a transformer:
|
||||
Transformers can be configured by extending `ldapOrgEntityProviderTransformExtensionPoint`. Here is an example:
|
||||
|
||||
```ts
|
||||
export async function myGroupTransformer(
|
||||
vendor: LdapVendor,
|
||||
config: GroupConfig,
|
||||
group: SearchEntry,
|
||||
): Promise<GroupEntity | undefined> {
|
||||
// Transformations may change namespace, change entity naming pattern, fill
|
||||
// profile with more or other details...
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
import { createBackendModule } from '@backstage/backend-plugin-api';
|
||||
import { ldapOrgEntityProviderTransformExtensionPoint } from '@backstage/plugin-catalog-backend-module-ldap';
|
||||
import { myUserTransformer, myGroupTransformer } from './transformers';
|
||||
|
||||
// Create the group entity on your own, or wrap the default transformer
|
||||
return await defaultGroupTransformer(vendor, config, group);
|
||||
}
|
||||
```
|
||||
|
||||
2. Configure the provider with the transformer:
|
||||
|
||||
```ts
|
||||
const ldapEntityProvider = LdapOrgEntityProvider.fromConfig(env.config, {
|
||||
id: 'our-ldap-master',
|
||||
target: 'ldaps://ds.example.net',
|
||||
logger: env.logger,
|
||||
groupTransformer: myGroupTransformer,
|
||||
});
|
||||
```
|
||||
|
||||
## Using a Processor instead of a Provider
|
||||
|
||||
An alternative to using the Provider for ingesting LDAP entries is to use a
|
||||
Processor. This is the old way that's based on registering locations with the
|
||||
proper type and target, triggering the processor to run.
|
||||
|
||||
The drawback of this method is that it will leave orphaned Group/User entities
|
||||
whenever they are deleted on your LDAP server, and you cannot control the
|
||||
frequency with which they are refreshed, separately from other processors.
|
||||
|
||||
### Processor Installation
|
||||
|
||||
The `LdapOrgReaderProcessor` is not registered by default, so you have to
|
||||
register it in the catalog plugin:
|
||||
|
||||
```typescript title="packages/backend/src/plugins/catalog.ts"
|
||||
builder.addProcessor(
|
||||
LdapOrgReaderProcessor.fromConfig(env.config, {
|
||||
logger: env.logger,
|
||||
backend.add(
|
||||
createBackendModule({
|
||||
pluginId: 'catalog',
|
||||
moduleId: 'ldap-extensions',
|
||||
register(env) {
|
||||
env.registerInit({
|
||||
deps: {
|
||||
/* highlight-add-start */
|
||||
ldapTransformers: ldapOrgEntityProviderTransformExtensionPoint,
|
||||
/* highlight-add-end */
|
||||
},
|
||||
async init({ ldapTransformers }) {
|
||||
/* highlight-add-start */
|
||||
ldapTransformers.setUserTransformer(myUserTransformer);
|
||||
ldapTransformers.setGroupTransformer(myGroupTransformer);
|
||||
/* highlight-add-end */
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
### Driving LDAP Org Processor Ingestion with Locations
|
||||
|
||||
Locations point out the specific org(s) you want to import. The `type` of these
|
||||
locations must be `ldap-org`, and the `target` must point to the exact URL
|
||||
(starting with `ldap://` or `ldaps://`) of the targeted LDAP server. You can
|
||||
have several such location entries if you want, but typically you will have just
|
||||
one.
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
- type: ldap-org
|
||||
target: ldaps://ds.example.net
|
||||
rules:
|
||||
- allow: [User, Group]
|
||||
```
|
||||
|
||||
### Example configurations
|
||||
|
||||
#### Google Secure LDAP Service
|
||||
|
||||
To sync Google Workspace/Cloud Identity organization data to users and groups in backstage,
|
||||
you must [configure Secure LDAP Service](https://support.google.com/a/answer/9048516) first.
|
||||
|
||||
Once Secure LDAP Service is configured, you can enable TLS options in LDAP configuration,
|
||||
as mentioned below. `keys` and `certs` specify the location of files that are generated
|
||||
while configuring Secure LDAP Service above.
|
||||
|
||||
```yaml
|
||||
ldap:
|
||||
providers:
|
||||
- target: ldaps://ldap.google.com:636
|
||||
tls:
|
||||
rejectUnauthorized: false
|
||||
keys: '/var/secrets/tls/gldap.key'
|
||||
certs: '/var/secrets/tls/gldap.crt'
|
||||
users:
|
||||
# users configuration comes here
|
||||
groups:
|
||||
# groups configuration comes here
|
||||
```
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -125,7 +125,7 @@ export class MyAwesomeApiClient implements MyAwesomeApi {
|
||||
|
||||
private async fetch<T = any>(input: string, init?: RequestInit): Promise<T> {
|
||||
// As configured previously for the backend proxy
|
||||
const proxyUri = '${await this.discoveryApi.getBaseUrl('proxy')}/<your-proxy-uri>';
|
||||
const proxyUri = `${await this.discoveryApi.getBaseUrl('proxy')}/<your-proxy-uri>`;
|
||||
|
||||
const resp = await fetch(`${proxyUri}${input}`, init);
|
||||
if (!resp.ok) throw new Error(resp);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: GraphQL Catalog
|
||||
author: Frontside Software
|
||||
authorUrl: https://frontside.com/
|
||||
category: Discovery
|
||||
description: Adds the GraphQL Endpoint to Backstage Catalog as a plugin.
|
||||
documentation: https://github.com/thefrontside/playhouse/blob/main/plugins/graphql-backend/README.md
|
||||
iconUrl: https://raw.githubusercontent.com/thefrontside/frontside.com/production/legacy/src/img/frontside-logo.png
|
||||
npmPackageName: '@frontside/backstage-plugin-graphql-backend'
|
||||
tags:
|
||||
- graphql
|
||||
- catalog
|
||||
- graphql-catalog
|
||||
addedDate: '2024-05-01'
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "root",
|
||||
"version": "1.28.0-next.0",
|
||||
"version": "1.28.0-next.1",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# example-app-next
|
||||
|
||||
## 0.0.12-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/cli@0.26.7-next.1
|
||||
- @backstage/plugin-catalog-import@0.12.0-next.1
|
||||
- @backstage/plugin-kubernetes@0.11.11-next.1
|
||||
- @backstage/plugin-search@1.4.12-next.1
|
||||
- @backstage/plugin-notifications@0.2.2-next.1
|
||||
- @backstage/plugin-scaffolder-react@1.8.7-next.1
|
||||
- @backstage/plugin-scaffolder@1.20.2-next.1
|
||||
- @backstage/plugin-catalog@1.20.1-next.1
|
||||
- @backstage/plugin-kubernetes-cluster@0.0.12-next.1
|
||||
- @backstage/plugin-catalog-react@1.12.1-next.0
|
||||
|
||||
## 0.0.12-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "example-app-next",
|
||||
"version": "0.0.12-next.0",
|
||||
"version": "0.0.12-next.1",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# example-app
|
||||
|
||||
## 0.2.98-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/cli@0.26.7-next.1
|
||||
- @backstage/plugin-catalog-import@0.12.0-next.1
|
||||
- @backstage/plugin-kubernetes@0.11.11-next.1
|
||||
- @backstage/plugin-search@1.4.12-next.1
|
||||
- @backstage/plugin-notifications@0.2.2-next.1
|
||||
- @backstage/plugin-scaffolder-react@1.8.7-next.1
|
||||
- @backstage/plugin-scaffolder@1.20.2-next.1
|
||||
- @backstage/plugin-catalog@1.20.1-next.1
|
||||
- @backstage/plugin-kubernetes-cluster@0.0.12-next.1
|
||||
- @backstage/plugin-catalog-react@1.12.1-next.0
|
||||
|
||||
## 0.2.98-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "example-app",
|
||||
"version": "0.2.98-next.0",
|
||||
"version": "0.2.98-next.1",
|
||||
"backstage": {
|
||||
"role": "frontend"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# @backstage/backend-app-api
|
||||
|
||||
## 0.7.6-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 398b82a: Add support for JWKS tokens in ExternalTokenHandler.
|
||||
- 9e63318: Added an optional `accessRestrictions` to external access service tokens and service principals in general, such that you can limit their access to certain plugins or permissions.
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/plugin-permission-node@0.7.30-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/cli-node@0.2.6-next.0
|
||||
- @backstage/config-loader@1.8.0
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
|
||||
## 0.7.6-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/backend-app-api",
|
||||
"version": "0.7.6-next.0",
|
||||
"version": "0.7.6-next.1",
|
||||
"description": "Core API used by Backstage backend apps",
|
||||
"backstage": {
|
||||
"role": "node-library"
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @backstage/backend-common
|
||||
|
||||
## 0.23.0-next.1
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 02103be: Deprecated and moved over core services to `@backstage/backend-defaults`
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-app-api@0.7.6-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/config-loader@1.8.0
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
|
||||
## 0.22.1-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/backend-common",
|
||||
"version": "0.22.1-next.0",
|
||||
"version": "0.23.0-next.1",
|
||||
"description": "Common functionality library for Backstage backends",
|
||||
"backstage": {
|
||||
"role": "node-library"
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# @backstage/backend-defaults
|
||||
|
||||
## 0.3.0-next.1
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 02103be: Deprecated and moved over core services to `@backstage/backend-defaults`
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-app-api@0.7.6-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/plugin-permission-node@0.7.30-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/config-loader@1.8.0
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
|
||||
## 0.2.19-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/backend-defaults",
|
||||
"version": "0.2.19-next.0",
|
||||
"version": "0.3.0-next.1",
|
||||
"description": "Backend defaults used by Backstage backend apps",
|
||||
"backstage": {
|
||||
"role": "node-library"
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# @backstage/backend-dynamic-feature-service
|
||||
|
||||
## 0.2.11-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-app-api@0.7.6-next.1
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/plugin-permission-node@0.7.30-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-backend@1.23.0-next.1
|
||||
- @backstage/cli-node@0.2.6-next.0
|
||||
- @backstage/config-loader@1.8.0
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
- @backstage/plugin-events-backend@0.3.6-next.1
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
- @backstage/plugin-scaffolder-node@0.4.5-next.1
|
||||
- @backstage/plugin-search-backend-node@1.2.24-next.1
|
||||
|
||||
## 0.2.11-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-dynamic-feature-service",
|
||||
"description": "Backstage dynamic feature service",
|
||||
"version": "0.2.11-next.0",
|
||||
"version": "0.2.11-next.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
# example-backend-legacy
|
||||
|
||||
## 0.2.99-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/plugin-permission-node@0.7.30-next.1
|
||||
- @backstage/plugin-search-backend@1.5.10-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-scaffolder-backend-module-gitlab@0.4.1-next.1
|
||||
- @backstage/plugin-kubernetes-backend@0.18.0-next.1
|
||||
- @backstage/plugin-catalog-backend@1.23.0-next.1
|
||||
- @backstage/plugin-scaffolder-backend@1.22.8-next.1
|
||||
- @backstage/plugin-app-backend@0.3.68-next.1
|
||||
- @backstage/plugin-auth-backend@0.22.6-next.1
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
- @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.17-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
- @backstage/plugin-devtools-backend@0.3.5-next.1
|
||||
- @backstage/plugin-events-backend@0.3.6-next.1
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
- @backstage/plugin-permission-backend@0.5.43-next.1
|
||||
- @backstage/plugin-proxy-backend@0.5.0-next.1
|
||||
- @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.20-next.1
|
||||
- @backstage/plugin-scaffolder-backend-module-rails@0.4.36-next.1
|
||||
- @backstage/plugin-search-backend-module-catalog@0.1.25-next.1
|
||||
- @backstage/plugin-search-backend-module-elasticsearch@1.4.2-next.1
|
||||
- @backstage/plugin-search-backend-module-explore@0.1.25-next.1
|
||||
- @backstage/plugin-search-backend-module-pg@0.5.28-next.1
|
||||
- @backstage/plugin-search-backend-module-techdocs@0.1.24-next.1
|
||||
- @backstage/plugin-search-backend-node@1.2.24-next.1
|
||||
- @backstage/plugin-signals-backend@0.1.5-next.1
|
||||
- @backstage/plugin-techdocs-backend@1.10.6-next.1
|
||||
- example-app@0.2.98-next.1
|
||||
- @backstage/plugin-catalog-backend-module-unprocessed@0.4.6-next.1
|
||||
- @backstage/plugin-signals-node@0.1.5-next.1
|
||||
|
||||
## 0.2.99-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "example-backend-legacy",
|
||||
"version": "0.2.99-next.0",
|
||||
"version": "0.2.99-next.1",
|
||||
"backstage": {
|
||||
"role": "backend"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @backstage/backend-plugin-api
|
||||
|
||||
## 0.6.19-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 9e63318: Added an optional `accessRestrictions` to external access service tokens and service principals in general, such that you can limit their access to certain plugins or permissions.
|
||||
- 0665b7e: Renamed `BackendPluginConfig`, `BackendModuleConfig`, and `ExtensionPointConfig` respectively to `CreateBackendPluginOptions`, `CreateBackendModuleOptions`, and `CreateExtensionPointOptions` to standardize frontend and backend factories signatures.
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
|
||||
## 0.6.19-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/backend-plugin-api",
|
||||
"version": "0.6.19-next.0",
|
||||
"version": "0.6.19-next.1",
|
||||
"description": "Core API used by Backstage backend plugins",
|
||||
"backstage": {
|
||||
"role": "node-library"
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @backstage/backend-tasks
|
||||
|
||||
## 0.5.24-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ed473cd: Updated the `TaskScheduleDefinitionConfig` deprecated comment to point to `SchedulerServiceTaskScheduleDefinitionConfig`
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
|
||||
## 0.5.24-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-tasks",
|
||||
"description": "Common distributed task management library for Backstage backends",
|
||||
"version": "0.5.24-next.0",
|
||||
"version": "0.5.24-next.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# @backstage/backend-test-utils
|
||||
|
||||
## 0.4.0-next.1
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 805cbe7: Added `TestCaches` that functions just like `TestDatabases`
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 9e63318: Made it possible to give access restrictions to `mockCredentials.service`
|
||||
- Updated dependencies
|
||||
- @backstage/backend-app-api@0.7.6-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
|
||||
## 0.3.9-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/backend-test-utils",
|
||||
"version": "0.3.9-next.0",
|
||||
"version": "0.4.0-next.1",
|
||||
"description": "Test helpers library for Backstage backends",
|
||||
"backstage": {
|
||||
"role": "node-library"
|
||||
|
||||
@@ -1,5 +1,39 @@
|
||||
# example-backend
|
||||
|
||||
## 0.0.27-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/plugin-permission-node@0.7.30-next.1
|
||||
- @backstage/plugin-search-backend@1.5.10-next.1
|
||||
- @backstage/backend-defaults@0.3.0-next.1
|
||||
- @backstage/plugin-kubernetes-backend@0.18.0-next.1
|
||||
- @backstage/plugin-catalog-backend@1.23.0-next.1
|
||||
- @backstage/plugin-scaffolder-backend@1.22.8-next.1
|
||||
- @backstage/plugin-notifications-backend@0.3.0-next.1
|
||||
- @backstage/plugin-app-backend@0.3.68-next.1
|
||||
- @backstage/plugin-auth-backend@0.22.6-next.1
|
||||
- @backstage/plugin-auth-backend-module-github-provider@0.1.16-next.0
|
||||
- @backstage/plugin-auth-backend-module-guest-provider@0.1.5-next.1
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
- @backstage/plugin-catalog-backend-module-openapi@0.1.37-next.1
|
||||
- @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.17-next.1
|
||||
- @backstage/plugin-devtools-backend@0.3.5-next.1
|
||||
- @backstage/plugin-permission-backend@0.5.43-next.1
|
||||
- @backstage/plugin-permission-backend-module-allow-all-policy@0.1.16-next.0
|
||||
- @backstage/plugin-proxy-backend@0.5.0-next.1
|
||||
- @backstage/plugin-scaffolder-backend-module-github@0.2.9-next.1
|
||||
- @backstage/plugin-search-backend-module-catalog@0.1.25-next.1
|
||||
- @backstage/plugin-search-backend-module-explore@0.1.25-next.1
|
||||
- @backstage/plugin-search-backend-module-techdocs@0.1.24-next.1
|
||||
- @backstage/plugin-search-backend-node@1.2.24-next.1
|
||||
- @backstage/plugin-signals-backend@0.1.5-next.1
|
||||
- @backstage/plugin-techdocs-backend@1.10.6-next.1
|
||||
- @backstage/plugin-catalog-backend-module-unprocessed@0.4.6-next.1
|
||||
|
||||
## 0.0.27-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "example-backend",
|
||||
"version": "0.0.27-next.0",
|
||||
"version": "0.0.27-next.1",
|
||||
"main": "dist/index.cjs.js",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/cli
|
||||
|
||||
## 0.26.7-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 788eca7: Fix readme for new plugins created using cli
|
||||
- c00f7ee: Fix issue with `esm` loaded dependencies being different from the `cjs` import for Vite dependencies
|
||||
- Updated dependencies
|
||||
- @backstage/cli-node@0.2.6-next.0
|
||||
- @backstage/config-loader@1.8.0
|
||||
|
||||
## 0.26.6-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/cli",
|
||||
"version": "0.26.6-next.0",
|
||||
"version": "0.26.7-next.1",
|
||||
"description": "CLI for developing Backstage plugins and apps",
|
||||
"backstage": {
|
||||
"role": "cli"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @backstage/create-app
|
||||
|
||||
## 0.5.16-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Bumped create-app version.
|
||||
|
||||
## 0.5.16-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/create-app",
|
||||
"description": "A CLI that helps you create your own Backstage app",
|
||||
"version": "0.5.16-next.0",
|
||||
"version": "0.5.16-next.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/repo-tools
|
||||
|
||||
## 0.9.1-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 8721a02: Add `--client-additional-properties` option to `openapi generate` command
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/cli-node@0.2.6-next.0
|
||||
- @backstage/config-loader@1.8.0
|
||||
|
||||
## 0.9.1-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/repo-tools",
|
||||
"description": "CLI for Backstage repo tooling ",
|
||||
"version": "0.9.1-next.0",
|
||||
"version": "0.9.1-next.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @techdocs/cli
|
||||
|
||||
## 1.8.12-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-techdocs-node@1.12.5-next.1
|
||||
|
||||
## 1.8.12-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@techdocs/cli",
|
||||
"description": "Utility CLI for managing TechDocs sites in Backstage.",
|
||||
"version": "1.8.12-next.0",
|
||||
"version": "1.8.12-next.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/plugin-app-backend
|
||||
|
||||
## 0.3.68-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/config-loader@1.8.0
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
|
||||
## 0.3.68-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/plugin-app-backend",
|
||||
"description": "A Backstage backend plugin that serves the Backstage frontend app",
|
||||
"version": "0.3.68-next.0",
|
||||
"version": "0.3.68-next.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/plugin-auth-backend-module-aws-alb-provider
|
||||
|
||||
## 0.1.11-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-auth-backend@0.22.6-next.1
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
|
||||
## 0.1.11-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/plugin-auth-backend-module-aws-alb-provider",
|
||||
"description": "The aws-alb provider module for the Backstage auth backend.",
|
||||
"version": "0.1.11-next.0",
|
||||
"version": "0.1.11-next.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @backstage/plugin-auth-backend-module-cloudflare-access-provider
|
||||
|
||||
## 0.1.2-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1354d81: Use `node-fetch` instead of native fetch, as per https://backstage.io/docs/architecture-decisions/adrs-adr013
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
|
||||
## 0.1.2-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-auth-backend-module-cloudflare-access-provider",
|
||||
"version": "0.1.2-next.0",
|
||||
"version": "0.1.2-next.1",
|
||||
"description": "The cloudflare-access-provider backend module for the auth plugin.",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @backstage/plugin-auth-backend-module-guest-provider
|
||||
|
||||
## 0.1.5-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
|
||||
## 0.1.5-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-auth-backend-module-guest-provider",
|
||||
"version": "0.1.5-next.0",
|
||||
"version": "0.1.5-next.1",
|
||||
"description": "The guest-provider backend module for the auth plugin.",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/plugin-auth-backend-module-oidc-provider
|
||||
|
||||
## 0.1.10-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-auth-backend@0.22.6-next.1
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
|
||||
## 0.1.10-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/plugin-auth-backend-module-oidc-provider",
|
||||
"description": "The oidc-provider backend module for the auth plugin.",
|
||||
"version": "0.1.10-next.0",
|
||||
"version": "0.1.10-next.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# @backstage/plugin-auth-backend
|
||||
|
||||
## 0.22.6-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.1.2-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-auth-backend-module-atlassian-provider@0.1.11-next.0
|
||||
- @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.11-next.1
|
||||
- @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.1.2-next.0
|
||||
- @backstage/plugin-auth-backend-module-bitbucket-provider@0.1.2-next.0
|
||||
- @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.14-next.0
|
||||
- @backstage/plugin-auth-backend-module-github-provider@0.1.16-next.0
|
||||
- @backstage/plugin-auth-backend-module-gitlab-provider@0.1.16-next.0
|
||||
- @backstage/plugin-auth-backend-module-google-provider@0.1.16-next.0
|
||||
- @backstage/plugin-auth-backend-module-microsoft-provider@0.1.14-next.0
|
||||
- @backstage/plugin-auth-backend-module-oauth2-provider@0.1.16-next.0
|
||||
- @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.12-next.0
|
||||
- @backstage/plugin-auth-backend-module-oidc-provider@0.1.10-next.1
|
||||
- @backstage/plugin-auth-backend-module-okta-provider@0.0.12-next.0
|
||||
- @backstage/plugin-auth-node@0.4.14-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.22.6-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-auth-backend",
|
||||
"version": "0.22.6-next.0",
|
||||
"version": "0.22.6-next.1",
|
||||
"description": "A Backstage backend plugin that handles authentication",
|
||||
"backstage": {
|
||||
"role": "backend-plugin"
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @backstage/plugin-auth-node
|
||||
|
||||
## 0.4.14-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
|
||||
## 0.4.14-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-auth-node",
|
||||
"version": "0.4.14-next.0",
|
||||
"version": "0.4.14-next.1",
|
||||
"backstage": {
|
||||
"role": "node-library"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @backstage/plugin-catalog-backend-module-aws
|
||||
|
||||
## 0.3.14-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-kubernetes-common@0.8.0-next.0
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.3.14-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-aws",
|
||||
"version": "0.3.14-next.0",
|
||||
"version": "0.3.14-next.1",
|
||||
"description": "A Backstage catalog backend module that helps integrate towards AWS",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/plugin-catalog-backend-module-azure
|
||||
|
||||
## 0.1.39-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.1.39-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-azure",
|
||||
"version": "0.1.39-next.0",
|
||||
"version": "0.1.39-next.1",
|
||||
"description": "A Backstage catalog backend module that helps integrate towards Azure",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @backstage/plugin-catalog-backend-module-bitbucket-cloud
|
||||
|
||||
## 0.2.6-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
|
||||
## 0.2.6-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud",
|
||||
"description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud",
|
||||
"version": "0.2.6-next.0",
|
||||
"version": "0.2.6-next.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/plugin-catalog-backend-module-bitbucket-server
|
||||
|
||||
## 0.1.33-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.1.33-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-bitbucket-server",
|
||||
"version": "0.1.33-next.0",
|
||||
"version": "0.1.33-next.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @backstage/plugin-catalog-backend-module-gcp
|
||||
|
||||
## 0.1.20-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-kubernetes-common@0.8.0-next.0
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.1.20-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-gcp",
|
||||
"version": "0.1.20-next.0",
|
||||
"version": "0.1.20-next.1",
|
||||
"description": "A Backstage catalog backend module that helps integrate towards GCP",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/plugin-catalog-backend-module-gerrit
|
||||
|
||||
## 0.1.36-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.1.36-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-gerrit",
|
||||
"version": "0.1.36-next.0",
|
||||
"version": "0.1.36-next.1",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @backstage/plugin-catalog-backend-module-github-org
|
||||
|
||||
## 0.1.14-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-backend-module-github@0.6.2-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
|
||||
## 0.1.14-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-github-org",
|
||||
"version": "0.1.14-next.0",
|
||||
"version": "0.1.14-next.1",
|
||||
"description": "The github-org backend module for the catalog plugin.",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @backstage/plugin-catalog-backend-module-github
|
||||
|
||||
## 0.6.2-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-backend@1.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
|
||||
## 0.6.2-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-github",
|
||||
"version": "0.6.2-next.0",
|
||||
"version": "0.6.2-next.1",
|
||||
"description": "A Backstage catalog backend module that helps integrate towards GitHub",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# @backstage/plugin-catalog-backend-module-gitlab-org
|
||||
|
||||
## 0.0.2-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/plugin-catalog-backend-module-gitlab@0.3.17-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
|
||||
## 0.0.2-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-gitlab-org",
|
||||
"version": "0.0.2-next.0",
|
||||
"version": "0.0.2-next.1",
|
||||
"description": "The gitlab-org backend module for the catalog plugin.",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# @backstage/plugin-catalog-backend-module-gitlab
|
||||
|
||||
## 0.3.17-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 150fc77: Fixed an issue in `GitlabOrgDiscoveryEntityProvider` where a missing `orgEnabled` config key was throwing an error.
|
||||
- f271164: Fixed an issue in `GitlabDiscoveryEntityProvider` where the fallback branch was taking precedence over the GitLab default branch.
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
|
||||
## 0.3.17-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-gitlab",
|
||||
"version": "0.3.17-next.0",
|
||||
"version": "0.3.17-next.1",
|
||||
"description": "A Backstage catalog backend module that helps integrate towards GitLab",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @backstage/plugin-catalog-backend-module-incremental-ingestion
|
||||
|
||||
## 0.4.24-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-backend@1.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
- @backstage/plugin-events-node@0.3.5-next.0
|
||||
|
||||
## 0.4.24-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-incremental-ingestion",
|
||||
"version": "0.4.24-next.0",
|
||||
"version": "0.4.24-next.1",
|
||||
"description": "An entity provider for streaming large asset sources into the catalog",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# @backstage/plugin-catalog-backend-module-ldap
|
||||
|
||||
## 0.6.0-next.1
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- debcc8c: Migrate LDAP catalog module to the new backend system.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.5.35-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -8,3 +8,7 @@ groups from your Active Directory or another LDAP compatible server.
|
||||
|
||||
See [Backstage documentation](https://backstage.io/docs/integrations/ldap/org) for details on how to install
|
||||
and configure the plugin.
|
||||
|
||||
## Legacy backend
|
||||
|
||||
You can find the legacy documentation at `docs/integrations/ldap/org--old.md`.
|
||||
|
||||
@@ -3,20 +3,26 @@
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { CatalogProcessor } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorEmit } from '@backstage/plugin-catalog-node';
|
||||
import { Client } from 'ldapjs';
|
||||
import { Config } from '@backstage/config';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-node';
|
||||
import { EntityProviderConnection } from '@backstage/plugin-catalog-node';
|
||||
import { ExtensionPoint } from '@backstage/backend-plugin-api';
|
||||
import { GroupEntity } from '@backstage/catalog-model';
|
||||
import { GroupTransformer as GroupTransformer_2 } from '@backstage/plugin-catalog-backend-module-ldap';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-common';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import { PluginTaskScheduler } from '@backstage/backend-tasks';
|
||||
import { SearchEntry } from 'ldapjs';
|
||||
import { SearchOptions } from 'ldapjs';
|
||||
import { TaskRunner } from '@backstage/backend-tasks';
|
||||
import { TaskScheduleDefinition } from '@backstage/backend-tasks';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
import { UserTransformer as UserTransformer_2 } from '@backstage/plugin-catalog-backend-module-ldap';
|
||||
|
||||
// @public
|
||||
export type BindConfig = {
|
||||
@@ -24,6 +30,10 @@ export type BindConfig = {
|
||||
secret: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
const catalogModuleLdapOrgEntityProvider: () => BackendFeature;
|
||||
export default catalogModuleLdapOrgEntityProvider;
|
||||
|
||||
// @public
|
||||
export function defaultGroupTransformer(
|
||||
vendor: LdapVendor,
|
||||
@@ -109,14 +119,19 @@ export class LdapOrgEntityProvider implements EntityProvider {
|
||||
static fromConfig(
|
||||
configRoot: Config,
|
||||
options: LdapOrgEntityProviderOptions,
|
||||
): LdapOrgEntityProvider[];
|
||||
// (undocumented)
|
||||
static fromLegacyConfig(
|
||||
configRoot: Config,
|
||||
options: LdapOrgEntityProviderLegacyOptions,
|
||||
): LdapOrgEntityProvider;
|
||||
// (undocumented)
|
||||
getProviderName(): string;
|
||||
read(options?: { logger?: LoggerService }): Promise<void>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface LdapOrgEntityProviderOptions {
|
||||
// @public @deprecated
|
||||
export interface LdapOrgEntityProviderLegacyOptions {
|
||||
groupTransformer?: GroupTransformer;
|
||||
id: string;
|
||||
logger: LoggerService;
|
||||
@@ -125,6 +140,30 @@ export interface LdapOrgEntityProviderOptions {
|
||||
userTransformer?: UserTransformer;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type LdapOrgEntityProviderOptions =
|
||||
| LdapOrgEntityProviderLegacyOptions
|
||||
| {
|
||||
logger: LoggerService;
|
||||
schedule?: 'manual' | TaskRunner;
|
||||
scheduler?: PluginTaskScheduler;
|
||||
userTransformer?: UserTransformer | Record<string, UserTransformer>;
|
||||
groupTransformer?: GroupTransformer | Record<string, GroupTransformer>;
|
||||
};
|
||||
|
||||
// @public
|
||||
export interface LdapOrgEntityProviderTransformsExtensionPoint {
|
||||
setGroupTransformer(
|
||||
transformer: GroupTransformer_2 | Record<string, GroupTransformer_2>,
|
||||
): void;
|
||||
setUserTransformer(
|
||||
transformer: UserTransformer_2 | Record<string, UserTransformer_2>,
|
||||
): void;
|
||||
}
|
||||
|
||||
// @public
|
||||
export const ldapOrgEntityProviderTransformsExtensionPoint: ExtensionPoint<LdapOrgEntityProviderTransformsExtensionPoint>;
|
||||
|
||||
// @public
|
||||
export class LdapOrgReaderProcessor implements CatalogProcessor {
|
||||
constructor(options: {
|
||||
@@ -154,11 +193,13 @@ export class LdapOrgReaderProcessor implements CatalogProcessor {
|
||||
|
||||
// @public
|
||||
export type LdapProviderConfig = {
|
||||
id: string;
|
||||
target: string;
|
||||
tls?: TLSConfig;
|
||||
bind?: BindConfig;
|
||||
users: UserConfig;
|
||||
groups: GroupConfig;
|
||||
schedule?: TaskScheduleDefinition;
|
||||
};
|
||||
|
||||
// @public
|
||||
@@ -176,8 +217,8 @@ export function mapStringAttr(
|
||||
setter: (value: string) => void,
|
||||
): void;
|
||||
|
||||
// @public
|
||||
export function readLdapConfig(config: Config): LdapProviderConfig[];
|
||||
// @public @deprecated
|
||||
export function readLdapLegacyConfig(config: Config): LdapProviderConfig[];
|
||||
|
||||
// @public
|
||||
export function readLdapOrg(
|
||||
@@ -194,6 +235,9 @@ export function readLdapOrg(
|
||||
groups: GroupEntity[];
|
||||
}>;
|
||||
|
||||
// @public
|
||||
export function readProviderConfigs(config: Config): LdapProviderConfig[];
|
||||
|
||||
// @public
|
||||
export type TLSConfig = {
|
||||
rejectUnauthorized?: boolean;
|
||||
|
||||
+229
-2
@@ -19,6 +19,8 @@ import { JsonValue } from '@backstage/types';
|
||||
export interface Config {
|
||||
/**
|
||||
* LdapOrgEntityProvider / LdapOrgReaderProcessor configuration
|
||||
*
|
||||
* @deprecated This exists for backwards compatibility only and will be removed in the future.
|
||||
*/
|
||||
ldap?: {
|
||||
/**
|
||||
@@ -240,12 +242,237 @@ export interface Config {
|
||||
|
||||
/**
|
||||
* Configuration options for the catalog plugin.
|
||||
*
|
||||
* TODO(freben): Deprecate this entire block
|
||||
*/
|
||||
catalog?: {
|
||||
/**
|
||||
* List of provider-specific options and attributes
|
||||
*/
|
||||
providers?: {
|
||||
/**
|
||||
* LdapOrg provider key
|
||||
*/
|
||||
ldapOrg: {
|
||||
/**
|
||||
* Id of the LdapOrg provider
|
||||
*/
|
||||
[id: string]: {
|
||||
/**
|
||||
* The prefix of the target that this matches on, e.g.
|
||||
* "ldaps://ds.example.net", with no trailing slash.
|
||||
*/
|
||||
target: string;
|
||||
|
||||
/**
|
||||
* The settings to use for the bind command. If none are specified,
|
||||
* the bind command is not issued.
|
||||
*/
|
||||
bind?: {
|
||||
/**
|
||||
* The DN of the user to auth as.
|
||||
*
|
||||
* E.g. "uid=ldap-robot,ou=robots,ou=example,dc=example,dc=net"
|
||||
*/
|
||||
dn: string;
|
||||
/**
|
||||
* The secret of the user to auth as (its password).
|
||||
*
|
||||
* @visibility secret
|
||||
*/
|
||||
secret: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* TLS settings
|
||||
*/
|
||||
tls?: {
|
||||
// Node TLS rejectUnauthorized
|
||||
rejectUnauthorized?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* The settings that govern the reading and interpretation of users.
|
||||
*/
|
||||
users: {
|
||||
/**
|
||||
* The DN under which users are stored.
|
||||
*
|
||||
* E.g. "ou=people,ou=example,dc=example,dc=net"
|
||||
*/
|
||||
dn: string;
|
||||
/**
|
||||
* The search options to use. The default is scope "one" and
|
||||
* attributes "*" and "+".
|
||||
*
|
||||
* It is common to want to specify a filter, to narrow down the set
|
||||
* of matching items.
|
||||
*/
|
||||
options: {
|
||||
scope?: 'base' | 'one' | 'sub';
|
||||
filter?: string;
|
||||
attributes?: string | string[];
|
||||
sizeLimit?: number;
|
||||
timeLimit?: number;
|
||||
derefAliases?: number;
|
||||
typesOnly?: boolean;
|
||||
paged?:
|
||||
| boolean
|
||||
| {
|
||||
pageSize?: number;
|
||||
pagePause?: boolean;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* JSON paths (on a.b.c form) and hard coded values to set on those
|
||||
* paths.
|
||||
*
|
||||
* This can be useful for example if you want to hard code a
|
||||
* namespace or similar on the generated entities.
|
||||
*/
|
||||
set?: { [key: string]: JsonValue };
|
||||
/**
|
||||
* Mappings from well known entity fields, to LDAP attribute names
|
||||
*/
|
||||
map?: {
|
||||
/**
|
||||
* The name of the attribute that holds the relative
|
||||
* distinguished name of each entry. Defaults to "uid".
|
||||
*/
|
||||
rdn?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the metadata.name field of the entity. Defaults to "uid".
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the metadata.description field of the entity.
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the spec.profile.displayName field of the entity. Defaults to
|
||||
* "cn".
|
||||
*/
|
||||
displayName?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the spec.profile.email field of the entity. Defaults to
|
||||
* "mail".
|
||||
*/
|
||||
email?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the spec.profile.picture field of the entity.
|
||||
*/
|
||||
picture?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the values of
|
||||
* the spec.memberOf field of the entity. Defaults to "memberOf".
|
||||
*/
|
||||
memberOf?: string;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* The settings that govern the reading and interpretation of groups.
|
||||
*/
|
||||
groups: {
|
||||
/**
|
||||
* The DN under which groups are stored.
|
||||
*
|
||||
* E.g. "ou=people,ou=example,dc=example,dc=net"
|
||||
*/
|
||||
dn: string;
|
||||
/**
|
||||
* The search options to use. The default is scope "one" and
|
||||
* attributes "*" and "+".
|
||||
*
|
||||
* It is common to want to specify a filter, to narrow down the set
|
||||
* of matching items.
|
||||
*/
|
||||
options: {
|
||||
scope?: 'base' | 'one' | 'sub';
|
||||
filter?: string;
|
||||
attributes?: string | string[];
|
||||
sizeLimit?: number;
|
||||
timeLimit?: number;
|
||||
derefAliases?: number;
|
||||
typesOnly?: boolean;
|
||||
paged?:
|
||||
| boolean
|
||||
| {
|
||||
pageSize?: number;
|
||||
pagePause?: boolean;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* JSON paths (on a.b.c form) and hard coded values to set on those
|
||||
* paths.
|
||||
*
|
||||
* This can be useful for example if you want to hard code a
|
||||
* namespace or similar on the generated entities.
|
||||
*/
|
||||
set?: { [key: string]: JsonValue };
|
||||
/**
|
||||
* Mappings from well known entity fields, to LDAP attribute names
|
||||
*/
|
||||
map?: {
|
||||
/**
|
||||
* The name of the attribute that holds the relative
|
||||
* distinguished name of each entry. Defaults to "cn".
|
||||
*/
|
||||
rdn?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the metadata.name field of the entity. Defaults to "cn".
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the metadata.description field of the entity. Defaults to
|
||||
* "description".
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the spec.type field of the entity. Defaults to "groupType".
|
||||
*/
|
||||
type?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the spec.profile.displayName field of the entity. Defaults to
|
||||
* "cn".
|
||||
*/
|
||||
displayName?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the spec.profile.email field of the entity.
|
||||
*/
|
||||
email?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the value of
|
||||
* the spec.profile.picture field of the entity.
|
||||
*/
|
||||
picture?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the values of
|
||||
* the spec.parent field of the entity. Defaults to "memberOf".
|
||||
*/
|
||||
memberOf?: string;
|
||||
/**
|
||||
* The name of the attribute that shall be used for the values of
|
||||
* the spec.children field of the entity. Defaults to "member".
|
||||
*/
|
||||
members?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* List of processor-specific options and attributes
|
||||
*
|
||||
* @deprecated This exists for backwards compatibility only and will be removed in the future.
|
||||
*/
|
||||
processors?: {
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-ldap",
|
||||
"version": "0.5.35-next.0",
|
||||
"version": "0.6.0-next.1",
|
||||
"description": "A Backstage catalog backend module that helps integrate towards LDAP",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -22,3 +22,8 @@
|
||||
|
||||
export * from './processors';
|
||||
export * from './ldap';
|
||||
export {
|
||||
catalogModuleLdapOrgEntityProvider as default,
|
||||
ldapOrgEntityProviderTransformsExtensionPoint,
|
||||
type LdapOrgEntityProviderTransformsExtensionPoint,
|
||||
} from './module';
|
||||
|
||||
@@ -15,26 +15,31 @@
|
||||
*/
|
||||
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { readLdapConfig } from './config';
|
||||
import { readProviderConfigs } from './config';
|
||||
|
||||
describe('readLdapConfig', () => {
|
||||
it('applies all of the defaults', () => {
|
||||
const config = {
|
||||
providers: [
|
||||
{
|
||||
target: 'target',
|
||||
users: {
|
||||
dn: 'udn',
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
catalog: {
|
||||
providers: {
|
||||
ldapOrg: {
|
||||
default: {
|
||||
target: 'target',
|
||||
users: {
|
||||
dn: 'udn',
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const actual = readLdapConfig(new ConfigReader(config));
|
||||
const actual = readProviderConfigs(new ConfigReader(config));
|
||||
const expected = [
|
||||
{
|
||||
id: 'default',
|
||||
target: 'target',
|
||||
bind: undefined,
|
||||
users: {
|
||||
@@ -76,72 +81,77 @@ describe('readLdapConfig', () => {
|
||||
|
||||
it('reads all the values', () => {
|
||||
const config = {
|
||||
providers: [
|
||||
{
|
||||
target: 'target',
|
||||
bind: { dn: 'bdn', secret: 's' },
|
||||
tls: {
|
||||
rejectUnauthorized: false,
|
||||
keys: '/tmp/keys.pem',
|
||||
certs: '/tmp/certs.pem',
|
||||
},
|
||||
users: {
|
||||
dn: 'udn',
|
||||
options: {
|
||||
scope: 'base',
|
||||
attributes: ['*'],
|
||||
filter: 'f',
|
||||
paged: true,
|
||||
timeLimit: 42,
|
||||
sizeLimit: 100,
|
||||
derefAliases: 0,
|
||||
typesOnly: false,
|
||||
},
|
||||
set: { p: 'v' },
|
||||
map: {
|
||||
rdn: 'u',
|
||||
name: 'v',
|
||||
description: 'd',
|
||||
displayName: 'c',
|
||||
email: 'm',
|
||||
picture: 'p',
|
||||
memberOf: 'm',
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
options: {
|
||||
scope: 'base',
|
||||
attributes: ['*'],
|
||||
filter: 'f',
|
||||
paged: {
|
||||
pageSize: 7,
|
||||
pagePause: true,
|
||||
catalog: {
|
||||
providers: {
|
||||
ldapOrg: {
|
||||
default: {
|
||||
target: 'target',
|
||||
bind: { dn: 'bdn', secret: 's' },
|
||||
tls: {
|
||||
rejectUnauthorized: false,
|
||||
keys: '/tmp/keys.pem',
|
||||
certs: '/tmp/certs.pem',
|
||||
},
|
||||
users: {
|
||||
dn: 'udn',
|
||||
options: {
|
||||
scope: 'base',
|
||||
attributes: ['*'],
|
||||
filter: 'f',
|
||||
paged: true,
|
||||
timeLimit: 42,
|
||||
sizeLimit: 100,
|
||||
derefAliases: 0,
|
||||
typesOnly: false,
|
||||
},
|
||||
set: { p: 'v' },
|
||||
map: {
|
||||
rdn: 'u',
|
||||
name: 'v',
|
||||
description: 'd',
|
||||
displayName: 'c',
|
||||
email: 'm',
|
||||
picture: 'p',
|
||||
memberOf: 'm',
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
options: {
|
||||
scope: 'base',
|
||||
attributes: ['*'],
|
||||
filter: 'f',
|
||||
paged: {
|
||||
pageSize: 7,
|
||||
pagePause: true,
|
||||
},
|
||||
timeLimit: 42,
|
||||
sizeLimit: 100,
|
||||
derefAliases: 1,
|
||||
typesOnly: true,
|
||||
},
|
||||
set: { p: 'v' },
|
||||
map: {
|
||||
rdn: 'u',
|
||||
name: 'v',
|
||||
description: 'd',
|
||||
type: 't',
|
||||
displayName: 'c',
|
||||
email: 'm',
|
||||
picture: 'p',
|
||||
memberOf: 'm',
|
||||
members: 'n',
|
||||
},
|
||||
},
|
||||
timeLimit: 42,
|
||||
sizeLimit: 100,
|
||||
derefAliases: 1,
|
||||
typesOnly: true,
|
||||
},
|
||||
set: { p: 'v' },
|
||||
map: {
|
||||
rdn: 'u',
|
||||
name: 'v',
|
||||
description: 'd',
|
||||
type: 't',
|
||||
displayName: 'c',
|
||||
email: 'm',
|
||||
picture: 'p',
|
||||
memberOf: 'm',
|
||||
members: 'n',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const actual = readLdapConfig(new ConfigReader(config));
|
||||
const actual = readProviderConfigs(new ConfigReader(config));
|
||||
const expected = [
|
||||
{
|
||||
id: 'default',
|
||||
target: 'target',
|
||||
bind: { dn: 'bdn', secret: 's' },
|
||||
tls: {
|
||||
@@ -207,30 +217,34 @@ describe('readLdapConfig', () => {
|
||||
|
||||
it('supports multiline ldap query filter', () => {
|
||||
const config = {
|
||||
providers: [
|
||||
{
|
||||
target: 'target',
|
||||
users: {
|
||||
dn: 'udn',
|
||||
options: {
|
||||
filter: `
|
||||
(|
|
||||
(cn=foo bar)
|
||||
(cn=bar)
|
||||
)
|
||||
`,
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
catalog: {
|
||||
providers: {
|
||||
ldapOrg: {
|
||||
default: {
|
||||
target: 'target',
|
||||
users: {
|
||||
dn: 'udn',
|
||||
options: {
|
||||
filter: `
|
||||
(|
|
||||
(cn=foo bar)
|
||||
(cn=bar)
|
||||
)
|
||||
`,
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const actual = readLdapConfig(new ConfigReader(config));
|
||||
const actual = readProviderConfigs(new ConfigReader(config));
|
||||
|
||||
const expected = '(|(cn=foo bar)(cn=bar))';
|
||||
expect(actual[0].users.options.filter).toEqual(expected);
|
||||
@@ -238,64 +252,72 @@ describe('readLdapConfig', () => {
|
||||
|
||||
it('supports a dot nested set structure', () => {
|
||||
const config = {
|
||||
providers: [
|
||||
{
|
||||
target: 'target',
|
||||
users: {
|
||||
dn: 'udn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
set: {
|
||||
'metadata.annotations': {
|
||||
a: 'b',
|
||||
catalog: {
|
||||
providers: {
|
||||
ldapOrg: {
|
||||
default: {
|
||||
target: 'target',
|
||||
users: {
|
||||
dn: 'udn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
set: {
|
||||
'metadata.annotations': {
|
||||
a: 'b',
|
||||
},
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
set: {
|
||||
x: { a: 'b' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
set: {
|
||||
x: { a: 'b' },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const actual = readLdapConfig(new ConfigReader(config));
|
||||
const actual = readProviderConfigs(new ConfigReader(config));
|
||||
|
||||
expect(actual[0].users.set).toEqual({ 'metadata.annotations': { a: 'b' } });
|
||||
});
|
||||
|
||||
it('throws on attempts to modify the set structure', () => {
|
||||
const config = {
|
||||
providers: [
|
||||
{
|
||||
target: 'target',
|
||||
users: {
|
||||
dn: 'udn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
set: {
|
||||
x: { a: 'b' },
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
set: {
|
||||
x: { a: 'b' },
|
||||
catalog: {
|
||||
providers: {
|
||||
ldapOrg: {
|
||||
default: {
|
||||
target: 'target',
|
||||
users: {
|
||||
dn: 'udn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
set: {
|
||||
x: { a: 'b' },
|
||||
},
|
||||
},
|
||||
groups: {
|
||||
dn: 'gdn',
|
||||
options: {
|
||||
filter: 'f',
|
||||
},
|
||||
set: {
|
||||
x: { a: 'b' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const actual = readLdapConfig(new ConfigReader(config));
|
||||
const actual = readProviderConfigs(new ConfigReader(config));
|
||||
|
||||
expect(() => {
|
||||
(actual[0].users.set as any).y = 2;
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
readTaskScheduleDefinitionFromConfig,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { Config } from '@backstage/config';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { SearchOptions } from 'ldapjs';
|
||||
@@ -27,6 +31,8 @@ import { RecursivePartial } from './util';
|
||||
* @public
|
||||
*/
|
||||
export type LdapProviderConfig = {
|
||||
// The id of the
|
||||
id: string;
|
||||
// The prefix of the target that this matches on, e.g.
|
||||
// "ldaps://ds.example.net", with no trailing slash.
|
||||
target: string;
|
||||
@@ -39,6 +45,8 @@ export type LdapProviderConfig = {
|
||||
users: UserConfig;
|
||||
// The settings that govern the reading and interpretation of groups
|
||||
groups: GroupConfig;
|
||||
// Schedule configuration for refresh tasks.
|
||||
schedule?: TaskScheduleDefinition;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -184,159 +192,160 @@ const defaultConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
function freeze<T>(data: T): T {
|
||||
return JSON.parse(JSON.stringify(data), (_key, value) => {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
Object.freeze(value);
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
function readTlsConfig(
|
||||
c: Config | undefined,
|
||||
): LdapProviderConfig['tls'] | undefined {
|
||||
if (!c) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
rejectUnauthorized: c.getOptionalBoolean('rejectUnauthorized'),
|
||||
keys: c.getOptionalString('keys'),
|
||||
certs: c.getOptionalString('certs'),
|
||||
};
|
||||
}
|
||||
|
||||
function readBindConfig(
|
||||
c: Config | undefined,
|
||||
): LdapProviderConfig['bind'] | undefined {
|
||||
if (!c) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
dn: c.getString('dn'),
|
||||
secret: c.getString('secret'),
|
||||
};
|
||||
}
|
||||
|
||||
function readOptionsConfig(c: Config | undefined): SearchOptions {
|
||||
if (!c) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const paged = readOptionsPagedConfig(c);
|
||||
|
||||
return {
|
||||
scope: c.getOptionalString('scope') as SearchOptions['scope'],
|
||||
filter: formatFilter(c.getOptionalString('filter')),
|
||||
attributes: c.getOptionalStringArray('attributes'),
|
||||
sizeLimit: c.getOptionalNumber('sizeLimit'),
|
||||
timeLimit: c.getOptionalNumber('timeLimit'),
|
||||
derefAliases: c.getOptionalNumber('derefAliases'),
|
||||
typesOnly: c.getOptionalBoolean('typesOnly'),
|
||||
...(paged !== undefined ? { paged } : undefined),
|
||||
};
|
||||
}
|
||||
|
||||
function readOptionsPagedConfig(c: Config): SearchOptions['paged'] {
|
||||
const pagedConfig = c.getOptional('paged');
|
||||
if (pagedConfig === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (pagedConfig === true || pagedConfig === false) {
|
||||
return pagedConfig;
|
||||
}
|
||||
|
||||
const pageSize = c.getOptionalNumber('paged.pageSize');
|
||||
const pagePause = c.getOptionalBoolean('paged.pagePause');
|
||||
return {
|
||||
...(pageSize !== undefined ? { pageSize } : undefined),
|
||||
...(pagePause !== undefined ? { pagePause } : undefined),
|
||||
};
|
||||
}
|
||||
|
||||
function readSetConfig(
|
||||
c: Config | undefined,
|
||||
): { [path: string]: JsonValue } | undefined {
|
||||
if (!c) {
|
||||
return undefined;
|
||||
}
|
||||
return c.get();
|
||||
}
|
||||
|
||||
function readUserMapConfig(
|
||||
c: Config | undefined,
|
||||
): Partial<LdapProviderConfig['users']['map']> {
|
||||
if (!c) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
rdn: c.getOptionalString('rdn'),
|
||||
name: c.getOptionalString('name'),
|
||||
description: c.getOptionalString('description'),
|
||||
displayName: c.getOptionalString('displayName'),
|
||||
email: c.getOptionalString('email'),
|
||||
picture: c.getOptionalString('picture'),
|
||||
memberOf: c.getOptionalString('memberOf'),
|
||||
};
|
||||
}
|
||||
|
||||
function readGroupMapConfig(
|
||||
c: Config | undefined,
|
||||
): Partial<LdapProviderConfig['groups']['map']> {
|
||||
if (!c) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
rdn: c.getOptionalString('rdn'),
|
||||
name: c.getOptionalString('name'),
|
||||
description: c.getOptionalString('description'),
|
||||
type: c.getOptionalString('type'),
|
||||
displayName: c.getOptionalString('displayName'),
|
||||
email: c.getOptionalString('email'),
|
||||
picture: c.getOptionalString('picture'),
|
||||
memberOf: c.getOptionalString('memberOf'),
|
||||
members: c.getOptionalString('members'),
|
||||
};
|
||||
}
|
||||
|
||||
function readUserConfig(
|
||||
c: Config,
|
||||
): RecursivePartial<LdapProviderConfig['users']> {
|
||||
return {
|
||||
dn: c.getString('dn'),
|
||||
options: readOptionsConfig(c.getOptionalConfig('options')),
|
||||
set: readSetConfig(c.getOptionalConfig('set')),
|
||||
map: readUserMapConfig(c.getOptionalConfig('map')),
|
||||
};
|
||||
}
|
||||
|
||||
function readGroupConfig(
|
||||
c: Config,
|
||||
): RecursivePartial<LdapProviderConfig['groups']> {
|
||||
return {
|
||||
dn: c.getString('dn'),
|
||||
options: readOptionsConfig(c.getOptionalConfig('options')),
|
||||
set: readSetConfig(c.getOptionalConfig('set')),
|
||||
map: readGroupMapConfig(c.getOptionalConfig('map')),
|
||||
};
|
||||
}
|
||||
|
||||
function formatFilter(filter?: string): string | undefined {
|
||||
// Remove extra whitespace between blocks to support multiline filters from the configuration
|
||||
return filter?.replace(/\s*(\(|\))/g, '$1')?.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses configuration.
|
||||
*
|
||||
* @param config - The root of the LDAP config hierarchy
|
||||
*
|
||||
* @public
|
||||
* @deprecated This exists for backwards compatibility only and will be removed in the future.
|
||||
*/
|
||||
export function readLdapConfig(config: Config): LdapProviderConfig[] {
|
||||
function freeze<T>(data: T): T {
|
||||
return JSON.parse(JSON.stringify(data), (_key, value) => {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
Object.freeze(value);
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
function readTlsConfig(
|
||||
c: Config | undefined,
|
||||
): LdapProviderConfig['tls'] | undefined {
|
||||
if (!c) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
rejectUnauthorized: c.getOptionalBoolean('rejectUnauthorized'),
|
||||
keys: c.getOptionalString('keys'),
|
||||
certs: c.getOptionalString('certs'),
|
||||
};
|
||||
}
|
||||
|
||||
function readBindConfig(
|
||||
c: Config | undefined,
|
||||
): LdapProviderConfig['bind'] | undefined {
|
||||
if (!c) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
dn: c.getString('dn'),
|
||||
secret: c.getString('secret'),
|
||||
};
|
||||
}
|
||||
|
||||
function readOptionsConfig(c: Config | undefined): SearchOptions {
|
||||
if (!c) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const paged = readOptionsPagedConfig(c);
|
||||
|
||||
return {
|
||||
scope: c.getOptionalString('scope') as SearchOptions['scope'],
|
||||
filter: formatFilter(c.getOptionalString('filter')),
|
||||
attributes: c.getOptionalStringArray('attributes'),
|
||||
sizeLimit: c.getOptionalNumber('sizeLimit'),
|
||||
timeLimit: c.getOptionalNumber('timeLimit'),
|
||||
derefAliases: c.getOptionalNumber('derefAliases'),
|
||||
typesOnly: c.getOptionalBoolean('typesOnly'),
|
||||
...(paged !== undefined ? { paged } : undefined),
|
||||
};
|
||||
}
|
||||
|
||||
function readOptionsPagedConfig(c: Config): SearchOptions['paged'] {
|
||||
const pagedConfig = c.getOptional('paged');
|
||||
if (pagedConfig === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (pagedConfig === true || pagedConfig === false) {
|
||||
return pagedConfig;
|
||||
}
|
||||
|
||||
const pageSize = c.getOptionalNumber('paged.pageSize');
|
||||
const pagePause = c.getOptionalBoolean('paged.pagePause');
|
||||
return {
|
||||
...(pageSize !== undefined ? { pageSize } : undefined),
|
||||
...(pagePause !== undefined ? { pagePause } : undefined),
|
||||
};
|
||||
}
|
||||
|
||||
function readSetConfig(
|
||||
c: Config | undefined,
|
||||
): { [path: string]: JsonValue } | undefined {
|
||||
if (!c) {
|
||||
return undefined;
|
||||
}
|
||||
return c.get();
|
||||
}
|
||||
|
||||
function readUserMapConfig(
|
||||
c: Config | undefined,
|
||||
): Partial<LdapProviderConfig['users']['map']> {
|
||||
if (!c) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
rdn: c.getOptionalString('rdn'),
|
||||
name: c.getOptionalString('name'),
|
||||
description: c.getOptionalString('description'),
|
||||
displayName: c.getOptionalString('displayName'),
|
||||
email: c.getOptionalString('email'),
|
||||
picture: c.getOptionalString('picture'),
|
||||
memberOf: c.getOptionalString('memberOf'),
|
||||
};
|
||||
}
|
||||
|
||||
function readGroupMapConfig(
|
||||
c: Config | undefined,
|
||||
): Partial<LdapProviderConfig['groups']['map']> {
|
||||
if (!c) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
rdn: c.getOptionalString('rdn'),
|
||||
name: c.getOptionalString('name'),
|
||||
description: c.getOptionalString('description'),
|
||||
type: c.getOptionalString('type'),
|
||||
displayName: c.getOptionalString('displayName'),
|
||||
email: c.getOptionalString('email'),
|
||||
picture: c.getOptionalString('picture'),
|
||||
memberOf: c.getOptionalString('memberOf'),
|
||||
members: c.getOptionalString('members'),
|
||||
};
|
||||
}
|
||||
|
||||
function readUserConfig(
|
||||
c: Config,
|
||||
): RecursivePartial<LdapProviderConfig['users']> {
|
||||
return {
|
||||
dn: c.getString('dn'),
|
||||
options: readOptionsConfig(c.getOptionalConfig('options')),
|
||||
set: readSetConfig(c.getOptionalConfig('set')),
|
||||
map: readUserMapConfig(c.getOptionalConfig('map')),
|
||||
};
|
||||
}
|
||||
|
||||
function readGroupConfig(
|
||||
c: Config,
|
||||
): RecursivePartial<LdapProviderConfig['groups']> {
|
||||
return {
|
||||
dn: c.getString('dn'),
|
||||
options: readOptionsConfig(c.getOptionalConfig('options')),
|
||||
set: readSetConfig(c.getOptionalConfig('set')),
|
||||
map: readGroupMapConfig(c.getOptionalConfig('map')),
|
||||
};
|
||||
}
|
||||
|
||||
function formatFilter(filter?: string): string | undefined {
|
||||
// Remove extra whitespace between blocks to support multiline filters from the configuration
|
||||
return filter?.replace(/\s*(\(|\))/g, '$1')?.trim();
|
||||
}
|
||||
|
||||
export function readLdapLegacyConfig(config: Config): LdapProviderConfig[] {
|
||||
const providerConfigs = config.getOptionalConfigArray('providers') ?? [];
|
||||
return providerConfigs.map(c => {
|
||||
const newConfig = {
|
||||
@@ -353,3 +362,40 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] {
|
||||
return freeze(merged) as LdapProviderConfig;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses all configured providers.
|
||||
*
|
||||
* @param config - The root of the LDAP config hierarchy
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function readProviderConfigs(config: Config): LdapProviderConfig[] {
|
||||
const providersConfig = config.getOptionalConfig('catalog.providers.ldapOrg');
|
||||
if (!providersConfig) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return providersConfig.keys().map(id => {
|
||||
const c = providersConfig.getConfig(id);
|
||||
|
||||
const schedule = c.has('schedule')
|
||||
? readTaskScheduleDefinitionFromConfig(c.getConfig('schedule'))
|
||||
: undefined;
|
||||
|
||||
const newConfig = {
|
||||
id,
|
||||
target: trimEnd(c.getString('target'), '/'),
|
||||
tls: readTlsConfig(c.getOptionalConfig('tls')),
|
||||
bind: readBindConfig(c.getOptionalConfig('bind')),
|
||||
users: readUserConfig(c.getConfig('users')),
|
||||
groups: readGroupConfig(c.getConfig('groups')),
|
||||
schedule,
|
||||
};
|
||||
const merged = mergeWith({}, defaultConfig, newConfig, (_into, from) => {
|
||||
// Replace arrays instead of merging, otherwise default behavior
|
||||
return Array.isArray(from) ? from : undefined;
|
||||
});
|
||||
return freeze(merged) as LdapProviderConfig;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
export { LdapClient } from './client';
|
||||
export { mapStringAttr } from './util';
|
||||
export { readLdapConfig } from './config';
|
||||
export { readProviderConfigs, readLdapLegacyConfig } from './config';
|
||||
export type {
|
||||
LdapProviderConfig,
|
||||
GroupConfig,
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
coreServices,
|
||||
createBackendModule,
|
||||
createExtensionPoint,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import {
|
||||
GroupTransformer,
|
||||
UserTransformer,
|
||||
} from '@backstage/plugin-catalog-backend-module-ldap';
|
||||
import { LdapOrgEntityProvider } from './processors';
|
||||
|
||||
/**
|
||||
* Interface for {@link LdapOrgEntityProviderTransformsExtensionPoint}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface LdapOrgEntityProviderTransformsExtensionPoint {
|
||||
/**
|
||||
* Set the function that transforms a user entry in LDAP to an entity.
|
||||
* Optionally, you can pass separate transformers per provider ID.
|
||||
*/
|
||||
setUserTransformer(
|
||||
transformer: UserTransformer | Record<string, UserTransformer>,
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Set the function that transforms a group entry in LDAP to an entity.
|
||||
* Optionally, you can pass separate transformers per provider ID.
|
||||
*/
|
||||
setGroupTransformer(
|
||||
transformer: GroupTransformer | Record<string, GroupTransformer>,
|
||||
): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension point used to customize the transforms used by the module.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const ldapOrgEntityProviderTransformsExtensionPoint =
|
||||
createExtensionPoint<LdapOrgEntityProviderTransformsExtensionPoint>({
|
||||
id: 'catalog.ldapOrgEntityProvider.transforms',
|
||||
});
|
||||
|
||||
/**
|
||||
* Registers the LdapOrgEntityProvider with the catalog processing extension point.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const catalogModuleLdapOrgEntityProvider = createBackendModule({
|
||||
pluginId: 'catalog',
|
||||
moduleId: 'ldapOrgEntityProvider',
|
||||
register(env) {
|
||||
let userTransformer:
|
||||
| UserTransformer
|
||||
| Record<string, UserTransformer>
|
||||
| undefined;
|
||||
let groupTransformer:
|
||||
| GroupTransformer
|
||||
| Record<string, GroupTransformer>
|
||||
| undefined;
|
||||
|
||||
env.registerExtensionPoint(ldapOrgEntityProviderTransformsExtensionPoint, {
|
||||
setUserTransformer(transformer) {
|
||||
if (userTransformer) {
|
||||
throw new Error('User transformer may only be set once');
|
||||
}
|
||||
userTransformer = transformer;
|
||||
},
|
||||
setGroupTransformer(transformer) {
|
||||
if (groupTransformer) {
|
||||
throw new Error('Group transformer may only be set once');
|
||||
}
|
||||
groupTransformer = transformer;
|
||||
},
|
||||
});
|
||||
|
||||
env.registerInit({
|
||||
deps: {
|
||||
catalog: catalogProcessingExtensionPoint,
|
||||
config: coreServices.rootConfig,
|
||||
logger: coreServices.logger,
|
||||
scheduler: coreServices.scheduler,
|
||||
},
|
||||
async init({ catalog, config, logger, scheduler }) {
|
||||
catalog.addEntityProvider(
|
||||
LdapOrgEntityProvider.fromConfig(config, {
|
||||
logger,
|
||||
scheduler,
|
||||
userTransformer: userTransformer,
|
||||
groupTransformer: groupTransformer,
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TaskRunner } from '@backstage/backend-tasks';
|
||||
import { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks';
|
||||
import {
|
||||
ANNOTATION_LOCATION,
|
||||
ANNOTATION_ORIGIN_LOCATION,
|
||||
@@ -32,18 +32,65 @@ import {
|
||||
LdapClient,
|
||||
LdapProviderConfig,
|
||||
LDAP_DN_ANNOTATION,
|
||||
readLdapConfig,
|
||||
readLdapOrg,
|
||||
UserTransformer,
|
||||
} from '../ldap';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import { readLdapLegacyConfig, readProviderConfigs } from '../ldap';
|
||||
|
||||
/**
|
||||
* Options for {@link LdapOrgEntityProvider}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface LdapOrgEntityProviderOptions {
|
||||
export type LdapOrgEntityProviderOptions =
|
||||
| LdapOrgEntityProviderLegacyOptions
|
||||
| {
|
||||
/**
|
||||
* The logger to use.
|
||||
*/
|
||||
logger: LoggerService;
|
||||
|
||||
/**
|
||||
* The refresh schedule to use.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* If you pass in 'manual', you are responsible for calling the `read` method
|
||||
* manually at some interval.
|
||||
*
|
||||
* But more commonly you will pass in the result of
|
||||
* {@link @backstage/backend-tasks#PluginTaskScheduler.createScheduledTaskRunner}
|
||||
* to enable automatic scheduling of tasks.
|
||||
*/
|
||||
schedule?: 'manual' | TaskRunner;
|
||||
|
||||
/**
|
||||
* Scheduler used to schedule refreshes based on
|
||||
* the schedule config.
|
||||
*/
|
||||
scheduler?: PluginTaskScheduler;
|
||||
|
||||
/**
|
||||
* The function that transforms a user entry in msgraph to an entity.
|
||||
* Optionally, you can pass separate transformers per provider ID.
|
||||
*/
|
||||
userTransformer?: UserTransformer | Record<string, UserTransformer>;
|
||||
|
||||
/**
|
||||
* The function that transforms a group entry in msgraph to an entity.
|
||||
* Optionally, you can pass separate transformers per provider ID.
|
||||
*/
|
||||
groupTransformer?: GroupTransformer | Record<string, GroupTransformer>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for {@link LdapOrgEntityProvider}.
|
||||
*
|
||||
* @public
|
||||
* @deprecated This interface exists for backwards compatibility only and will be removed in the future.
|
||||
*/
|
||||
export interface LdapOrgEntityProviderLegacyOptions {
|
||||
/**
|
||||
* A unique, stable identifier for this provider.
|
||||
*
|
||||
@@ -109,12 +156,68 @@ export class LdapOrgEntityProvider implements EntityProvider {
|
||||
static fromConfig(
|
||||
configRoot: Config,
|
||||
options: LdapOrgEntityProviderOptions,
|
||||
): LdapOrgEntityProvider[] {
|
||||
if ('id' in options) {
|
||||
return [LdapOrgEntityProvider.fromLegacyConfig(configRoot, options)];
|
||||
}
|
||||
|
||||
if (!options.schedule && !options.scheduler) {
|
||||
throw new Error('Either schedule or scheduler must be provided.');
|
||||
}
|
||||
|
||||
function getTransformer<T extends Function>(
|
||||
id: string,
|
||||
transformers?: T | Record<string, T>,
|
||||
): T | undefined {
|
||||
if (['undefined', 'function'].includes(typeof transformers)) {
|
||||
return transformers as T;
|
||||
}
|
||||
|
||||
return (transformers as Record<string, T>)[id];
|
||||
}
|
||||
|
||||
return readProviderConfigs(configRoot).map(providerConfig => {
|
||||
if (!options.schedule && !providerConfig.schedule) {
|
||||
throw new Error(
|
||||
`No schedule provided neither via code nor config for LdapOrgEntityProvider:${providerConfig.id}.`,
|
||||
);
|
||||
}
|
||||
|
||||
const taskRunner =
|
||||
options.schedule ??
|
||||
options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!);
|
||||
|
||||
const provider = new LdapOrgEntityProvider({
|
||||
id: providerConfig.id,
|
||||
provider: providerConfig,
|
||||
logger: options.logger,
|
||||
userTransformer: getTransformer(
|
||||
providerConfig.id,
|
||||
options.userTransformer,
|
||||
),
|
||||
groupTransformer: getTransformer(
|
||||
providerConfig.id,
|
||||
options.groupTransformer,
|
||||
),
|
||||
});
|
||||
|
||||
if (taskRunner !== 'manual') {
|
||||
provider.schedule(taskRunner);
|
||||
}
|
||||
|
||||
return provider;
|
||||
});
|
||||
}
|
||||
|
||||
static fromLegacyConfig(
|
||||
configRoot: Config,
|
||||
options: LdapOrgEntityProviderLegacyOptions,
|
||||
): LdapOrgEntityProvider {
|
||||
// TODO(freben): Deprecate the old catalog.processors.ldapOrg config
|
||||
const config =
|
||||
configRoot.getOptionalConfig('ldap') ||
|
||||
configRoot.getOptionalConfig('catalog.processors.ldapOrg');
|
||||
const providers = config ? readLdapConfig(config) : [];
|
||||
const providers = config ? readLdapLegacyConfig(config) : [];
|
||||
const provider = providers.find(p => options.target === p.target);
|
||||
if (!provider) {
|
||||
throw new TypeError(
|
||||
@@ -134,7 +237,9 @@ export class LdapOrgEntityProvider implements EntityProvider {
|
||||
logger,
|
||||
});
|
||||
|
||||
result.schedule(options.schedule);
|
||||
if (options.schedule !== 'manual') {
|
||||
result.schedule(options.schedule);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -206,14 +311,10 @@ export class LdapOrgEntityProvider implements EntityProvider {
|
||||
markCommitComplete();
|
||||
}
|
||||
|
||||
private schedule(schedule: LdapOrgEntityProviderOptions['schedule']) {
|
||||
if (schedule === 'manual') {
|
||||
return;
|
||||
}
|
||||
|
||||
private schedule(taskRunner: TaskRunner) {
|
||||
this.scheduleFn = async () => {
|
||||
const id = `${this.getProviderName()}:refresh`;
|
||||
await schedule.run({
|
||||
await taskRunner.run({
|
||||
id,
|
||||
fn: async () => {
|
||||
const logger = this.options.logger.child({
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
GroupTransformer,
|
||||
LdapClient,
|
||||
LdapProviderConfig,
|
||||
readLdapConfig,
|
||||
readLdapLegacyConfig,
|
||||
readLdapOrg,
|
||||
UserTransformer,
|
||||
} from '../ldap';
|
||||
@@ -56,7 +56,7 @@ export class LdapOrgReaderProcessor implements CatalogProcessor {
|
||||
configRoot.getOptionalConfig('catalog.processors.ldapOrg');
|
||||
return new LdapOrgReaderProcessor({
|
||||
...options,
|
||||
providers: config ? readLdapConfig(config) : [],
|
||||
providers: config ? readLdapLegacyConfig(config) : [],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,5 +15,8 @@
|
||||
*/
|
||||
|
||||
export { LdapOrgEntityProvider } from './LdapOrgEntityProvider';
|
||||
export type { LdapOrgEntityProviderOptions } from './LdapOrgEntityProvider';
|
||||
export type {
|
||||
LdapOrgEntityProviderOptions,
|
||||
LdapOrgEntityProviderLegacyOptions,
|
||||
} from './LdapOrgEntityProvider';
|
||||
export { LdapOrgReaderProcessor } from './LdapOrgReaderProcessor';
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/plugin-catalog-backend-module-msgraph
|
||||
|
||||
## 0.5.27-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-tasks@0.5.24-next.1
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.5.27-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-catalog-backend-module-msgraph",
|
||||
"version": "0.5.27-next.0",
|
||||
"version": "0.5.27-next.1",
|
||||
"description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph",
|
||||
"backstage": {
|
||||
"role": "backend-plugin-module"
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/plugin-catalog-backend-module-openapi
|
||||
|
||||
## 0.1.37-next.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@0.6.19-next.1
|
||||
- @backstage/backend-common@0.23.0-next.1
|
||||
- @backstage/plugin-catalog-backend@1.23.0-next.1
|
||||
- @backstage/plugin-catalog-node@1.12.1-next.0
|
||||
|
||||
## 0.1.37-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user