backstage / backstage

Backstage is an open framework for building developer portals
https://backstage.io/
Apache License 2.0
28.12k stars 5.96k forks source link

šŸš€ Feature: catalog client in coreServices #27220

Open grantila opened 2 weeks ago

grantila commented 2 weeks ago

šŸ”– Feature description

Add the CatalogClient into coreServices for use in the backends, and allow an async getToken() function to be passed to the CatalogClient. The coreServices catalog client would then create a service token for each request (as is expected in backends).

šŸŽ¤ Context

Today, everywhere in backends when calls to the catalog are made, one has to:

      const { token } = await this.auth.getPluginRequestToken({
        onBehalfOf: await this.auth.getOwnServiceCredentials(),
        targetPluginId: 'catalog',
      });

and then feed that token into each and every catalog call. You're not supposed to cache this either, but create a new one for each call, to ensure it's updated if necessary. This is cumbersome, and bloats code quite a bit.

It would be a fairly simple task to add an optional callback in the CatalogClient to an async getToken() which would simplify using the catalog (and have this invoked in every API function it has automatically). And even nicer (and a fairly simple contribution) to add this to the coreServices, so you don't even need to do that.

I get that you want to keep backend-plugin-api slim and dependency light, but the catalog client is most likely used (and imported) anyway in a backend, in practically all Backstage instances. If you'd prefer, this service could be a separate package too.

I'm willing to contribute this, if you think it's a good idea. Either just the getToken() in the CatalogClient, or a backend service as well.

āœŒļø Possible Implementation

No response

šŸ‘€ Have you spent some time to check if this feature request has been raised before?

šŸ¢ Have you read the Code of Conduct?

Are you willing to submit PR?

Yes I am willing to submit a PR!

freben commented 2 weeks ago

One problem here is the onBehalfOf. What token to use depends on the context and the client currently has absolutely no way of knowing which one to use. Is this being done "as the service itself" (pure service token), or for the user (on-behalf-of token)? This is critically important for having the right permissions apply. And it's potentially different on a per-call basis, not per-client-instance.

I'm not necessarily against adding the catalog client to the core services (personally), but we may want to look into the interface first. Most likely, if it were a core service, it wouldn't accept a token argument but instead a credentials argument or similar.

Maybe there's even things we can do in terms of storing the current incoming user identity in request handlers using continuation-local storage so it can be picked up transparently when present. But that's a bit more of a wild random thought, let's not build that upfront :)

Rugvip commented 2 weeks ago

Fixing the credentials bit in #27234